From 25aebee16ed6a944249d6312a97902a6677c00be Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 4 Jan 2024 15:41:32 +0530 Subject: [PATCH 001/124] API-Endpoint support for sun-net-httpserver --- .../sun-net-httpserver/build.gradle | 4 ++++ .../HttpContext_Instrumentation.java | 23 +++++++++++++++++++ .../sun/net/httpserver/HttpServerHelper.java | 1 + .../HttpServer_Instrumentation.java | 22 ++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpContext_Instrumentation.java create mode 100644 instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServer_Instrumentation.java diff --git a/instrumentation-security/sun-net-httpserver/build.gradle b/instrumentation-security/sun-net-httpserver/build.gradle index 89575877f..28649f7f9 100644 --- a/instrumentation-security/sun-net-httpserver/build.gradle +++ b/instrumentation-security/sun-net-httpserver/build.gradle @@ -6,4 +6,8 @@ dependencies { jar { manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.sun-net-httpserver' } +} + +verifyInstrumentation { + passes("com.sun.net.httpserver:http:20070405") } \ No newline at end of file diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpContext_Instrumentation.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpContext_Instrumentation.java new file mode 100644 index 000000000..4de7f71ea --- /dev/null +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpContext_Instrumentation.java @@ -0,0 +1,23 @@ +package com.sun.net.httpserver; + +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +import static com.sun.net.httpserver.HttpServerHelper.HTTP_METHOD; + +@Weave(originalName = "com.sun.net.httpserver.HttpContext", type = MatchType.BaseClass) +public abstract class HttpContext_Instrumentation { + public abstract String getPath(); + + public void setHandler (HttpHandler h) { + try { + Weaver.callOriginal(); + } finally { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(HTTP_METHOD, getPath(), h.getClass().getName())); + } + } + +} diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java index ca8cd20bb..570116da5 100644 --- a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java @@ -22,6 +22,7 @@ public class HttpServerHelper { public static final String HTTPS_PROTOCOL = "https"; private static final String REQUEST_INPUTSTREAM_HASH = "REQUEST_INPUTSTREAM_HASH"; public static final String SUN_NET_READER_OPERATION_LOCK = "SUN_NET_READER_OPERATION_LOCK-"; + public static final String HTTP_METHOD = "*"; public static void processHttpRequestHeaders(Headers headers, HttpRequest securityRequest){ for (String headerKey : headers.keySet()) { diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServer_Instrumentation.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServer_Instrumentation.java new file mode 100644 index 000000000..42dcf740c --- /dev/null +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServer_Instrumentation.java @@ -0,0 +1,22 @@ +package com.sun.net.httpserver; + +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +import static com.sun.net.httpserver.HttpServerHelper.HTTP_METHOD; + +@Weave(originalName = "com.sun.net.httpserver.HttpServer", type = MatchType.BaseClass) +public class HttpServer_Instrumentation { + public HttpContext createContext (String path, HttpHandler handler){ + HttpContext context; + try { + context = Weaver.callOriginal(); + } finally { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(HTTP_METHOD, path, handler.getClass().getName())); + } + return context; + } +} From f88687602d6af301e97a9b3b15187f4bc922e114 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 4 Jan 2024 15:42:13 +0530 Subject: [PATCH 002/124] added API-Endpoint unit tests for sun-net-httpserver --- .../httpServer/test/HttpServerTest.java | 22 +++++++++++++++++++ .../httpServer/test/Httpserver.java | 6 +++++ 2 files changed, 28 insertions(+) diff --git a/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java b/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java index 74b263c61..b2faf9f90 100644 --- a/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java +++ b/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java @@ -6,7 +6,9 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import org.junit.Assert; @@ -21,8 +23,10 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; @RunWith(SecurityInstrumentationTestRunner.class) @@ -121,6 +125,24 @@ public void testHandle2() throws URISyntaxException, IOException, InterruptedExc Assert.assertEquals("Wrong hashcode detected", Collections.singleton(expectedHash), introspector.getRequestInStreamHash()); } + @Test + public void testURLMapping() { + Iterator urlMappings = URLMappingsHelper.getApplicationURLMappings().iterator(); + Assert.assertTrue("should have elements", urlMappings.hasNext()); + + ApplicationURLMapping urlMapping = urlMappings.next(); + Assert.assertEquals("invalid handler", Httpserver.Handler.class.getName(), urlMapping.getHandler()); + Assert.assertEquals("invalid http-method", "*", urlMapping.getMethod()); + Assert.assertEquals("invalid path", "/", urlMapping.getPath()); + + Assert.assertTrue("should have elements", urlMappings.hasNext()); + + urlMapping = urlMappings.next(); + Assert.assertEquals("invalid handler", Httpserver.Handler.class.getName(), urlMapping.getHandler()); + Assert.assertEquals("invalid http-method", "*", urlMapping.getMethod()); + Assert.assertEquals("invalid path", "/new", urlMapping.getPath()); + } + @Trace(dispatcher = true) private void handle() throws URISyntaxException, IOException { URL url = server.getEndPoint().toURL(); diff --git a/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/Httpserver.java b/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/Httpserver.java index 9af1c767c..12a32c704 100644 --- a/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/Httpserver.java +++ b/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/Httpserver.java @@ -1,5 +1,6 @@ package com.nr.agent.security.instrumentation.httpServer.test; +import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; @@ -29,7 +30,12 @@ protected void after() { public void startServer() throws IOException { server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), PORT), 0); server.createContext("/", new Handler()); + + // creating HttpContext and will specify the handler later + HttpContext context = server.createContext("/new"); server.setExecutor(null); + + context.setHandler(new Handler()); server.start(); } From f28fbe84e1bbcfa6563b865ca8c62cde0062075f Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 16 Jan 2024 18:33:27 +0530 Subject: [PATCH 003/124] added play framework API endpoint support --- .../play-2.13_2.7/build.gradle | 32 +++++++++++++++++ .../GeneratedRouter_Instrumentation.scala | 34 +++++++++++++++++++ .../play-2.4/build.gradle | 31 +++++++++++++++++ .../GeneratedRouter_Instrumentation.scala | 33 ++++++++++++++++++ .../play-2.6/build.gradle | 29 ++++++++++++++++ .../GeneratedRouter_Instrumentation.scala | 33 ++++++++++++++++++ settings.gradle | 3 ++ 7 files changed, 195 insertions(+) create mode 100644 instrumentation-security/play-2.13_2.7/build.gradle create mode 100644 instrumentation-security/play-2.13_2.7/src/main/scala/com/newrelic/agent/security/instrumentation/play2_13/GeneratedRouter_Instrumentation.scala create mode 100644 instrumentation-security/play-2.4/build.gradle create mode 100644 instrumentation-security/play-2.4/src/main/scala/com/newrelic/agent/security/instrumentation/play24/GeneratedRouter_Instrumentation.scala create mode 100644 instrumentation-security/play-2.6/build.gradle create mode 100644 instrumentation-security/play-2.6/src/main/scala/com/newrelic/agent/security/instrumentation/play26/GeneratedRouter_Instrumentation.scala diff --git a/instrumentation-security/play-2.13_2.7/build.gradle b/instrumentation-security/play-2.13_2.7/build.gradle new file mode 100644 index 000000000..670053f82 --- /dev/null +++ b/instrumentation-security/play-2.13_2.7/build.gradle @@ -0,0 +1,32 @@ +apply plugin: 'scala' + +scala { + zincVersion = "1.7.1" +} +isScalaProjectEnabled(project, "scala-2.13") + +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("org.scala-lang:scala-library:2.13.12") + implementation("com.typesafe.play:play_2.13:2.7.3") +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.play-2.13_2.7' } +} + +verifyInstrumentation { + passesOnly 'com.typesafe.play:play_2.13:[2.7.0-M1,)' + passesOnly 'org.playframework:play_2.13:[3.0.0-M1,)' + passesOnly 'org.playframework:play_3:[3.0.0-M1,)' + + // build snapshots + excludeRegex '.*-[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]{7}$' +} + +site { + title 'Play' + type 'Appserver' +} \ No newline at end of file diff --git a/instrumentation-security/play-2.13_2.7/src/main/scala/com/newrelic/agent/security/instrumentation/play2_13/GeneratedRouter_Instrumentation.scala b/instrumentation-security/play-2.13_2.7/src/main/scala/com/newrelic/agent/security/instrumentation/play2_13/GeneratedRouter_Instrumentation.scala new file mode 100644 index 000000000..31735382b --- /dev/null +++ b/instrumentation-security/play-2.13_2.7/src/main/scala/com/newrelic/agent/security/instrumentation/play2_13/GeneratedRouter_Instrumentation.scala @@ -0,0 +1,34 @@ +package com.newrelic.agent.security.instrumentation.play2_13 + +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper +import com.newrelic.api.agent.security.schema.ApplicationURLMapping +import com.newrelic.api.agent.weaver.{MatchType, Weave, Weaver} +import play.api.routing.HandlerDef +import play.core.routing.{HandlerInvoker, HandlerInvokerFactory} + +import scala.jdk.CollectionConverters.SeqHasAsJava + + +@Weave(originalName = "play.core.routing.GeneratedRouter", `type` = MatchType.BaseClass) +abstract class GeneratedRouter_Instrumentation { + + def documentation: scala.collection.immutable.Seq[(String, String, String)] + + def createInvoker[T](fakeCall: => T, handlerDef: HandlerDef)(implicit hif: HandlerInvokerFactory[T]): HandlerInvoker[T] = { + try { + Weaver.callOriginal() + } finally { + gatherURLMappings() + } + } + + private def gatherURLMappings(): Unit = { + val iterator = documentation.asJava.iterator() + while (iterator.hasNext){ + val doc = iterator.next + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(doc._1, doc._2, doc._3)) + } + } +} + + diff --git a/instrumentation-security/play-2.4/build.gradle b/instrumentation-security/play-2.4/build.gradle new file mode 100644 index 000000000..7360567ab --- /dev/null +++ b/instrumentation-security/play-2.4/build.gradle @@ -0,0 +1,31 @@ +apply plugin: 'scala' + +isScalaProjectEnabled(project, "scala-2.10") + +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("org.scala-lang:scala-library:2.11.12") + implementation("com.typesafe.play:play_2.11:2.4.0") +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.play-2.4' } +} + +verifyInstrumentation { + passesOnly 'com.typesafe.play:play_2.11:[2.4.0-M3,2.6.0-M1)' + passesOnly 'com.typesafe.play:play_2.10:[2.4.0-M3,)' + + fails 'com.typesafe.play:play_2.10:2.3.10' + fails 'com.typesafe.play:play_2.11:2.3.10' + + // build snapshots + excludeRegex '.*-[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]{7}$' +} + +site { + title 'Play' + type 'Appserver' +} \ No newline at end of file diff --git a/instrumentation-security/play-2.4/src/main/scala/com/newrelic/agent/security/instrumentation/play24/GeneratedRouter_Instrumentation.scala b/instrumentation-security/play-2.4/src/main/scala/com/newrelic/agent/security/instrumentation/play24/GeneratedRouter_Instrumentation.scala new file mode 100644 index 000000000..bd0f4b043 --- /dev/null +++ b/instrumentation-security/play-2.4/src/main/scala/com/newrelic/agent/security/instrumentation/play24/GeneratedRouter_Instrumentation.scala @@ -0,0 +1,33 @@ +package com.newrelic.agent.security.instrumentation.play24 + +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper +import com.newrelic.api.agent.security.schema.ApplicationURLMapping +import com.newrelic.api.agent.weaver.{MatchType, Weave, Weaver} +import play.core.routing.{HandlerDef, HandlerInvoker, HandlerInvokerFactory} + +import scala.collection.JavaConverters.asJavaIterableConverter + + +@Weave(originalName = "play.core.routing.GeneratedRouter", `type` = MatchType.BaseClass) +abstract class GeneratedRouter_Instrumentation { + + def documentation: Seq[(String, String, String)] + + def createInvoker[T](fakeCall: => T, handlerDef: HandlerDef)(implicit hif: HandlerInvokerFactory[T]): HandlerInvoker[T] = { + try { + Weaver.callOriginal() + } finally { + gatherURLMappings() + } + } + + private def gatherURLMappings(): Unit = { + val iterator = documentation.asJava.iterator() + while (iterator.hasNext){ + val doc = iterator.next + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(doc._1, doc._2, doc._3)) + } + } +} + + diff --git a/instrumentation-security/play-2.6/build.gradle b/instrumentation-security/play-2.6/build.gradle new file mode 100644 index 000000000..81829d203 --- /dev/null +++ b/instrumentation-security/play-2.6/build.gradle @@ -0,0 +1,29 @@ +apply plugin: 'scala' + +isScalaProjectEnabled(project, "scala-2.11") + +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("org.scala-lang:scala-library:2.11.12") + implementation("com.typesafe.play:play_2.11:2.7.0") +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.play-2.6' } +} + +verifyInstrumentation { + passesOnly 'com.typesafe.play:play_2.12:[2.6.0-M1,)' + passesOnly 'com.typesafe.play:play_2.11:[2.6.0-M1,)' + fails 'com.typesafe.play:play_2.13:[2.7.0-M1,)' + + // build snapshots + excludeRegex '.*-[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]{7}$' +} + +site { + title 'Play' + type 'Appserver' +} \ No newline at end of file diff --git a/instrumentation-security/play-2.6/src/main/scala/com/newrelic/agent/security/instrumentation/play26/GeneratedRouter_Instrumentation.scala b/instrumentation-security/play-2.6/src/main/scala/com/newrelic/agent/security/instrumentation/play26/GeneratedRouter_Instrumentation.scala new file mode 100644 index 000000000..ca821c948 --- /dev/null +++ b/instrumentation-security/play-2.6/src/main/scala/com/newrelic/agent/security/instrumentation/play26/GeneratedRouter_Instrumentation.scala @@ -0,0 +1,33 @@ +package com.newrelic.agent.security.instrumentation.play26 + +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper +import com.newrelic.api.agent.security.schema.ApplicationURLMapping +import com.newrelic.api.agent.weaver.{MatchType, Weave, Weaver} +import play.api.routing.HandlerDef +import play.core.routing.{HandlerInvoker, HandlerInvokerFactory} + +import scala.collection.JavaConverters.asJavaIterableConverter + +@Weave(originalName = "play.core.routing.GeneratedRouter", `type` = MatchType.BaseClass) +abstract class GeneratedRouter_Instrumentation { + + def documentation: Seq[(String, String, String)] + + def createInvoker[T](fakeCall: => T, handlerDef: HandlerDef)(implicit hif: HandlerInvokerFactory[T]): HandlerInvoker[T] = { + try { + Weaver.callOriginal() + } finally { + gatherURLMappings() + } + } + + private def gatherURLMappings(): Unit = { + val iterator = documentation.asJava.iterator() + while (iterator.hasNext){ + val doc = iterator.next + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(doc._1, doc._2, doc._3)) + } + } +} + + diff --git a/settings.gradle b/settings.gradle index 19e86c4f8..2e90f6593 100644 --- a/settings.gradle +++ b/settings.gradle @@ -157,3 +157,6 @@ include 'instrumentation:async-http-client-2.0.0' include 'instrumentation:sun-net-httpserver' include 'instrumentation:tomcat-7' include 'instrumentation:tomcat-8' +include 'instrumentation:play-2.4' +include 'instrumentation:play-2.6' +include 'instrumentation:play-2.13_2.7' From 491513ebee8e27478e8fd5d95b2952b62ea1e07c Mon Sep 17 00:00:00 2001 From: idawda Date: Sun, 21 Jan 2024 08:55:07 +0530 Subject: [PATCH 004/124] API endpoint support for CXF Jax-rs --- .../cxf-jaxrs/build.gradle | 21 ++++++++ .../java/security/cxf/jaxrs/CXFHelper.java | 51 +++++++++++++++++++ .../cxf/jaxrs/JAXRSServerFactoryBean.java | 22 ++++++++ settings.gradle | 1 + 4 files changed, 95 insertions(+) create mode 100644 instrumentation-security/cxf-jaxrs/build.gradle create mode 100644 instrumentation-security/cxf-jaxrs/src/main/java/com/newrelic/agent/java/security/cxf/jaxrs/CXFHelper.java create mode 100644 instrumentation-security/cxf-jaxrs/src/main/java/com/newrelic/agent/java/security/cxf/jaxrs/JAXRSServerFactoryBean.java diff --git a/instrumentation-security/cxf-jaxrs/build.gradle b/instrumentation-security/cxf-jaxrs/build.gradle new file mode 100644 index 000000000..86f45b0ec --- /dev/null +++ b/instrumentation-security/cxf-jaxrs/build.gradle @@ -0,0 +1,21 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation('org.apache.cxf:cxf-rt-frontend-jaxrs:2.1.4') +} + + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.cxf-jaxrs' } +} + + +verifyInstrumentation { + passesOnly 'org.apache.cxf:cxf-rt-frontend-jaxrs:[2.1.4,)' +} + +site { + title 'CXF' + type 'Framework' +} \ No newline at end of file diff --git a/instrumentation-security/cxf-jaxrs/src/main/java/com/newrelic/agent/java/security/cxf/jaxrs/CXFHelper.java b/instrumentation-security/cxf-jaxrs/src/main/java/com/newrelic/agent/java/security/cxf/jaxrs/CXFHelper.java new file mode 100644 index 000000000..129337df7 --- /dev/null +++ b/instrumentation-security/cxf-jaxrs/src/main/java/com/newrelic/agent/java/security/cxf/jaxrs/CXFHelper.java @@ -0,0 +1,51 @@ +package com.newrelic.agent.java.security.cxf.jaxrs; + +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import org.apache.cxf.jaxrs.model.ClassResourceInfo; +import org.apache.cxf.jaxrs.model.MethodDispatcher; +import org.apache.cxf.jaxrs.model.OperationResourceInfo; + +import java.util.List; + +public class CXFHelper { + private static final String EMPTY = ""; + private static final String SEPARATOR = "/"; + private static final String WILDCARD = "*"; + + public static void gatherURLMapping(List classResourceInfo) { + for (ClassResourceInfo classResource: classResourceInfo){ + resources(classResource.getURITemplate().getValue(), classResource); + } + } + + private static void resources(String segment, ClassResourceInfo classResourceInfo) { + MethodDispatcher methodDispatcher = classResourceInfo.getMethodDispatcher(); + for(OperationResourceInfo method: methodDispatcher.getOperationResourceInfos()) { + String segment1 = method.getURITemplate().getValue(); + String path = segment + ((segment.endsWith(SEPARATOR) || segment1.startsWith(SEPARATOR)) ? EMPTY : SEPARATOR) + segment1; + + // http-method is null, then it can be a sub-resource + if (method.getHttpMethod() == null){ + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping( + WILDCARD, + path + (path.endsWith(SEPARATOR) ? EMPTY : SEPARATOR) + WILDCARD, + classResourceInfo.getResourceClass().getName() + )); + } else { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping( + method.getHttpMethod(), + path, + classResourceInfo.getResourceClass().getName() + )); + } + + } + // for sub-resources + for (ClassResourceInfo classResource: classResourceInfo.getSubResources()){ + String segment1 = classResource.getURITemplate().getValue(); + String path = segment + ((segment.endsWith(SEPARATOR) || segment1.startsWith(SEPARATOR)) ? EMPTY : SEPARATOR) + segment1; + resources(path, classResource); + } + } +} diff --git a/instrumentation-security/cxf-jaxrs/src/main/java/com/newrelic/agent/java/security/cxf/jaxrs/JAXRSServerFactoryBean.java b/instrumentation-security/cxf-jaxrs/src/main/java/com/newrelic/agent/java/security/cxf/jaxrs/JAXRSServerFactoryBean.java new file mode 100644 index 000000000..76c9421cf --- /dev/null +++ b/instrumentation-security/cxf-jaxrs/src/main/java/com/newrelic/agent/java/security/cxf/jaxrs/JAXRSServerFactoryBean.java @@ -0,0 +1,22 @@ +package com.newrelic.agent.java.security.cxf.jaxrs; + +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import org.apache.cxf.endpoint.Server; +import org.apache.cxf.jaxrs.JAXRSServiceFactoryBean; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.cxf.jaxrs.JAXRSServerFactoryBean") +public abstract class JAXRSServerFactoryBean { + public abstract JAXRSServiceFactoryBean getServiceFactory(); + + public Server create() { + try { + return Weaver.callOriginal(); + } finally { + CXFHelper.gatherURLMapping(getServiceFactory().getClassResourceInfo()); + } + } + + +} diff --git a/settings.gradle b/settings.gradle index 19e86c4f8..1b7aec29f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -157,3 +157,4 @@ include 'instrumentation:async-http-client-2.0.0' include 'instrumentation:sun-net-httpserver' include 'instrumentation:tomcat-7' include 'instrumentation:tomcat-8' +include 'instrumentation:cxf-jaxrs' From 1b9f53ef3fd0d6ec16e19beb013518696242448e Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 12 Feb 2024 19:44:35 +0530 Subject: [PATCH 005/124] UTs for API endpoint support for CXF Jax-RS --- .../cxf-jaxrs/build.gradle | 2 + .../cxf/jaxrs/APIEndpointTest.java | 79 +++++++++++++++++++ .../jaxrs/app/CustomerLocatorResource.java | 22 ++++++ .../cxf/jaxrs/app/TestMapping.java | 32 ++++++++ 4 files changed, 135 insertions(+) create mode 100644 instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/APIEndpointTest.java create mode 100644 instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/app/CustomerLocatorResource.java create mode 100644 instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/app/TestMapping.java diff --git a/instrumentation-security/cxf-jaxrs/build.gradle b/instrumentation-security/cxf-jaxrs/build.gradle index 86f45b0ec..e131a5522 100644 --- a/instrumentation-security/cxf-jaxrs/build.gradle +++ b/instrumentation-security/cxf-jaxrs/build.gradle @@ -3,6 +3,8 @@ dependencies { implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation('org.apache.cxf:cxf-rt-frontend-jaxrs:2.1.4') + + implementation('org.apache.cxf:cxf-rt-transports-http-jetty:2.1.4') } diff --git a/instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/APIEndpointTest.java b/instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/APIEndpointTest.java new file mode 100644 index 000000000..b4268abed --- /dev/null +++ b/instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/APIEndpointTest.java @@ -0,0 +1,79 @@ +package com.nr.agent.security.instrumentation.cxf.jaxrs; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.nr.agent.security.instrumentation.cxf.jaxrs.app.CustomerLocatorResource; +import com.nr.agent.security.instrumentation.cxf.jaxrs.app.TestMapping; +import org.apache.cxf.endpoint.Server; +import org.apache.cxf.jaxrs.JAXRSBindingFactory; +import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; +import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.net.ServerSocket; +import java.util.Iterator; +import java.util.Set; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = "com.newrelic.agent.java.security.cxf.jaxrs") +public class APIEndpointTest { + private final String handler = TestMapping.class.getName(); + + @Test + public void testAPIEndpoint() { + startServer(); + + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertEquals(5, mappings.size()); + + Iterator mapping = mappings.iterator(); + String path = "/users/"; + + Assert.assertTrue(mapping.hasNext()); + assertMapping("*", "/customers/orders/*", CustomerLocatorResource.class.getName(), mapping.next()); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("POST", path, handler, mapping.next()); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("GET", path, handler, mapping.next()); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("PUT", path, handler, mapping.next()); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("GET", path +"count", handler, mapping.next()); + + } + + private void assertMapping(String method, String path, String handler, ApplicationURLMapping actualMapping) { + Assert.assertEquals(method, actualMapping.getMethod()); + Assert.assertEquals(path, actualMapping.getPath()); + Assert.assertEquals(handler, actualMapping.getHandler()); + } + + private void startServer() { + JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); + + sf.setResourceClasses(CustomerLocatorResource.class, TestMapping.class); + + sf.setBindingFactory(new JAXRSBindingFactory()); + + sf.setAddress("http://localhost:" + getRandomPort()); + Server myServer = sf.create(); + myServer.start(); + } + + private int getRandomPort() { + try (ServerSocket socket = new ServerSocket(0)){ + return socket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Unable to allocate ephemeral port"); + } + } +} diff --git a/instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/app/CustomerLocatorResource.java b/instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/app/CustomerLocatorResource.java new file mode 100644 index 000000000..65e129133 --- /dev/null +++ b/instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/app/CustomerLocatorResource.java @@ -0,0 +1,22 @@ +package com.nr.agent.security.instrumentation.cxf.jaxrs.app; + +import javax.ws.rs.Path; + +@Path("/customers") +public class CustomerLocatorResource { + protected OrdersSubResource ordersSubResource = new OrdersSubResource(); + + @Path("orders") + public Object getOrders() { + return ordersSubResource; + } +} +class OrdersSubResource { + protected TestMapping idType = new TestMapping(); + + @Path("getStuff") + public Object getById() { + return idType; + } + +} diff --git a/instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/app/TestMapping.java b/instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/app/TestMapping.java new file mode 100644 index 000000000..76c4e964a --- /dev/null +++ b/instrumentation-security/cxf-jaxrs/src/test/java/com/nr/agent/security/instrumentation/cxf/jaxrs/app/TestMapping.java @@ -0,0 +1,32 @@ +package com.nr.agent.security.instrumentation.cxf.jaxrs.app; + +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; + +@Path("users") +public class TestMapping { + @PUT + public String putIt() { + return "Put it!"; + } + + @POST + public String postIt() { + return "Post it!"; + } + + @GET + public String getIt() { + return "Get it!"; + } + + @Path("count") + @GET + public String pathIt() { + return "path it!"; + } +} + + From 9a624ef7fdd9f0c633efd174c5de4b804c85c052 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 14 Feb 2024 19:16:40 +0530 Subject: [PATCH 006/124] enabled posting data to SE --- .../agent/security/intcodeagent/websocket/WSClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSClient.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSClient.java index feef8d793..d2f07257d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSClient.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSClient.java @@ -4,6 +4,7 @@ import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.dispatcher.DispatcherPool; import com.newrelic.agent.security.instrumentator.httpclient.RestRequestThreadPool; +import com.newrelic.agent.security.instrumentator.utils.AgentUtils; import com.newrelic.agent.security.instrumentator.utils.INRSettingsKey; import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessor; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; @@ -191,7 +192,7 @@ public void onOpen(ServerHandshake handshakedata) { WSUtils.getInstance().notifyAll(); } WSUtils.getInstance().setConnected(true); -// AgentUtils.sendApplicationURLMappings(); + AgentUtils.sendApplicationURLMappings(); logger.logInit(LogLevel.INFO, String.format(IAgentConstants.APPLICATION_INFO_SENT_ON_WS_CONNECT, AgentInfo.getInstance().getApplicationInfo()), WSClient.class.getName()); } From 5b575c4618e3b0260235f421923711148921930e Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 14 Feb 2024 19:17:24 +0530 Subject: [PATCH 007/124] enabled API endpoint support --- settings.gradle | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/settings.gradle b/settings.gradle index cd1f7debf..8d5411519 100644 --- a/settings.gradle +++ b/settings.gradle @@ -142,20 +142,20 @@ include 'instrumentation:file-low-priority-instrumentation' include 'instrumentation:cassandra-datastax-3' include 'instrumentation:cassandra-datastax-4' include 'instrumentation:commons-jxpath' -//include 'instrumentation:grails-1.3' -//include 'instrumentation:grails-2.0' -//include 'instrumentation:grails-3.0' -//include 'instrumentation:resteasy-2.2' -//include 'instrumentation:resteasy-3' -//include 'instrumentation:resteasy-4' -//include 'instrumentation:jersey' -//include 'instrumentation:apache-struts2' -//include 'instrumentation:spring-webflux' -//include 'instrumentation:spring-webmvc-3.1.0' -//include 'instrumentation:spring-webmvc-5.3.0' -//include 'instrumentation:apache-wicket-6.4' -//include 'instrumentation:apache-wicket-7.0' -//include 'instrumentation:apache-wicket-8.0' +include 'instrumentation:grails-1.3' +include 'instrumentation:grails-2.0' +include 'instrumentation:grails-3.0' +include 'instrumentation:resteasy-2.2' +include 'instrumentation:resteasy-3' +include 'instrumentation:resteasy-4' +include 'instrumentation:jersey' +include 'instrumentation:apache-struts2' +include 'instrumentation:spring-webflux' +include 'instrumentation:spring-webmvc-3.1.0' +include 'instrumentation:spring-webmvc-5.3.0' +include 'instrumentation:apache-wicket-6.4' +include 'instrumentation:apache-wicket-7.0' +include 'instrumentation:apache-wicket-8.0' include 'instrumentation:async-http-client-2.0.0' include 'instrumentation:sun-net-httpserver' include 'instrumentation:tomcat-7' From 746b63b6588b9d3b29393f90994f4eda3bfb5864 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 15 Feb 2024 18:29:50 +0530 Subject: [PATCH 008/124] Unit Tests for API endpoint support for play-2.6 --- .../play-2.6/build.gradle | 47 ++++++++++++ .../play26/APIEndpointTest.java | 74 +++++++++++++++++++ .../play26/PlayApplicationServerRule.java | 60 +++++++++++++++ .../play26/SimpleJavaAction.java | 61 +++++++++++++++ .../play26/SimpleJavaController.java | 39 ++++++++++ .../play26/SimpleScalaController.scala | 24 ++++++ .../play-2.6/src/test/resources/conf/routes | 5 ++ 7 files changed, 310 insertions(+) create mode 100644 instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/APIEndpointTest.java create mode 100644 instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/PlayApplicationServerRule.java create mode 100644 instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleJavaAction.java create mode 100644 instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleJavaController.java create mode 100644 instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleScalaController.scala create mode 100644 instrumentation-security/play-2.6/src/test/resources/conf/routes diff --git a/instrumentation-security/play-2.6/build.gradle b/instrumentation-security/play-2.6/build.gradle index 81829d203..c0bf094d1 100644 --- a/instrumentation-security/play-2.6/build.gradle +++ b/instrumentation-security/play-2.6/build.gradle @@ -1,13 +1,36 @@ +import play.routes.compiler.InjectedRoutesGenerator$ +import play.routes.compiler.RoutesCompiler +import play.routes.compiler.RoutesCompiler$ + apply plugin: 'scala' isScalaProjectEnabled(project, "scala-2.11") +sourceSets.test.scala.srcDir "src/test/java" +sourceSets.test.java.srcDirs = [] + +compileJava.options.bootstrapClasspath = null + +buildscript { + dependencies { + classpath 'com.typesafe.play:routes-compiler_2.13:2.7.3' + } + repositories { + mavenCentral() + } +} + dependencies { implementation(project(":newrelic-security-api")) implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation("org.scala-lang:scala-library:2.11.12") implementation("com.typesafe.play:play_2.11:2.7.0") + testImplementation("com.typesafe.play:routes-compiler_2.11:2.7.0") + testImplementation("com.typesafe.play:play-test_2.11:2.7.0") + testImplementation("com.typesafe.play:play-akka-http-server_2.11:2.7.0") + testImplementation("com.typesafe.play:play-java_2.11:2.7.0") + testImplementation("jakarta.xml.ws:jakarta.xml.ws-api:2.3.3") } jar { @@ -23,6 +46,30 @@ verifyInstrumentation { excludeRegex '.*-[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]{7}$' } +compileTestScala { + def routeFile = file("src/test/resources/conf/routes") + def generatedSourcesDir = layout.buildDirectory.dir("generated/scala") + + options.compilerArgs += '-proc:none' + + inputs.file(routeFile) + localState.register(generatedSourcesDir) + + // this manually compiles the conf/routes file into an Routes.scala file, which is subsequently read on startup by our test application + doFirst { + def RoutesCompiler.RoutesCompilerTask routesCompilerTask = new RoutesCompiler.RoutesCompilerTask( + routeFile, scala.collection.immutable.List$.MODULE$.empty().toSeq(), true, false, false) + RoutesCompiler$.MODULE$.compile(routesCompilerTask, InjectedRoutesGenerator$.MODULE$, generatedSourcesDir.get().asFile) + source generatedSourcesDir + scala.collection.immutable.List$.MODULE$.empty() + } +} + +clean { + // Clean up any residual generated Routes files to avoid duplicate classes + delete 'src/test/scala/router' +} + site { title 'Play' type 'Appserver' diff --git a/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/APIEndpointTest.java b/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/APIEndpointTest.java new file mode 100644 index 000000000..1a1f0ca4e --- /dev/null +++ b/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/APIEndpointTest.java @@ -0,0 +1,74 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.nr.agent.security.instrumentation.play26; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.security.test.marker.Java17IncompatibleTest; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + +@Category({ Java17IncompatibleTest.class }) +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = { "com.newrelic.agent.security.instrumentation.play26" }) +public class APIEndpointTest { + + @ClassRule + public static PlayApplicationServerRule serverRule = new PlayApplicationServerRule(); + + private static final Map expectedMappings = new HashMap<>(); + + @BeforeClass + public static void setupMappings() { + expectedMappings.put("/hello", SimpleJavaController.class.getName() + ".hello"); + expectedMappings.put("/scalaHello", SimpleScalaController.class.getName() + ".scalaHello"); + expectedMappings.put("/post", SimpleJavaController.class.getName() + ".post(data:String)"); + expectedMappings.put("/index", SimpleJavaController.class.getName() + ".index"); + expectedMappings.put("/simple", SimpleJavaController.class.getName() + ".simple"); + } + + @Test + public void testControllerActions() throws IOException { + HttpURLConnection conn = ((HttpURLConnection) serverRule.getEndpoint("/hello").openConnection()); + conn.connect(); + System.out.println(conn.getResponseCode()); + + Set actualMappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertNotNull(actualMappings); + Assert.assertEquals(5, actualMappings.size()); + for (ApplicationURLMapping actualMapping : actualMappings) { + assertMappings(actualMapping); + } + } + + private void assertMappings(ApplicationURLMapping actualMapping){ + Assert.assertNotNull(actualMapping.getPath()); + Assert.assertNotNull(actualMapping.getHandler()); + Assert.assertNotNull(actualMapping.getMethod()); + + String path = actualMapping.getPath(); + String handler = expectedMappings.get(path); + String method = !path.equals("/post") ? "GET" : "POST"; + + Assert.assertEquals(handler, actualMapping.getHandler()); + Assert.assertEquals(method, actualMapping.getMethod()); + } +} \ No newline at end of file diff --git a/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/PlayApplicationServerRule.java b/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/PlayApplicationServerRule.java new file mode 100644 index 000000000..399f228e3 --- /dev/null +++ b/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/PlayApplicationServerRule.java @@ -0,0 +1,60 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.nr.agent.security.instrumentation.play26; + +import org.junit.rules.ExternalResource; +import play.Application; +import play.inject.guice.GuiceApplicationBuilder; +import play.test.Helpers; +import play.test.TestServer; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.ServerSocket; +import java.net.URL; + +import static play.inject.Bindings.bind; + +public class PlayApplicationServerRule extends ExternalResource { + private TestServer server; + private int port; + + public PlayApplicationServerRule() { + this.port = getRandomPort(); + } + + @Override + protected void before() throws Throwable { + Application application = new GuiceApplicationBuilder() + .bindings( + bind(SimpleJavaController.class).toSelf().eagerly(), + bind(SimpleScalaController.class).toSelf().eagerly(), + bind(SimpleJavaAction.class).toSelf().eagerly()) + .build(); + + server = Helpers.testServer(port, application); + server.start(); + } + + @Override + protected void after() { + server.stop(); + } + + private int getRandomPort() { + try (ServerSocket socket = new ServerSocket(0)){ + return socket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Unable to allocate ephemeral PORT"); + } + } + + public URL getEndpoint(String path) throws MalformedURLException { + return new URL("http://localhost:" + port + path); + } +} diff --git a/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleJavaAction.java b/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleJavaAction.java new file mode 100644 index 000000000..41919ca65 --- /dev/null +++ b/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleJavaAction.java @@ -0,0 +1,61 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.nr.agent.security.instrumentation.play26; + + +import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.TimeUnit; +import javax.inject.Inject; + +import play.Logger; +import play.libs.concurrent.Futures; +import play.libs.concurrent.HttpExecutionContext; +import play.mvc.Http; +import play.mvc.Result; +import play.mvc.Results; + +import static play.mvc.Http.Status.GATEWAY_TIMEOUT; + +public class SimpleJavaAction extends play.mvc.Action.Simple { + private final Logger.ALogger logger = Logger.of("application.SimpleJavaAction"); + + private final HttpExecutionContext ec; + private final Futures futures; + + @Inject + public SimpleJavaAction(HttpExecutionContext ec, Futures futures) { + this.ec = ec; + this.futures = futures; + } + + public CompletionStage call(Http.Request req) { + if (logger.isTraceEnabled()) { + logger.trace("call: req = " + req); + } + + return futures.timeout(doCall(req), 1L, TimeUnit.SECONDS).exceptionally(e -> + (Results.status(GATEWAY_TIMEOUT, "No"))); + } + + private CompletionStage doCall(Http.Request req) { + return delegate.call(req).handleAsync((result, e) -> { + if (e != null) { + if (e instanceof CompletionException) { + logger.error("Direct exception " + e.getMessage(), e); + return internalServerError(); + } else { + logger.error("Unknown exception " + e.getMessage(), e); + return internalServerError(); + } + } else { + return result; + } + }, ec.current()); + } +} \ No newline at end of file diff --git a/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleJavaController.java b/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleJavaController.java new file mode 100644 index 000000000..6df3468e2 --- /dev/null +++ b/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleJavaController.java @@ -0,0 +1,39 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.nr.agent.security.instrumentation.play26; + +import javax.inject.Inject; + +import play.libs.concurrent.HttpExecutionContext; +import play.mvc.Controller; +import play.mvc.Result; +import play.mvc.With; + +@With(SimpleJavaAction.class) +public class SimpleJavaController extends Controller { + private HttpExecutionContext ec; + + @Inject + public SimpleJavaController(HttpExecutionContext ec) { + this.ec = ec; + } + + public Result post(String data) { return ok("Received data: " + data).as("text/plain");} + public Result hello() { + return ok("hello world").as("text/plain"); + } + + public Result index() { + return ok("Index Page").as("text/plain"); + } + + public Result simple() { + return ok("Simple test").as("text/plain"); + } + +} diff --git a/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleScalaController.scala b/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleScalaController.scala new file mode 100644 index 000000000..4a9259baf --- /dev/null +++ b/instrumentation-security/play-2.6/src/test/java/com/nr/agent/security/instrumentation/play26/SimpleScalaController.scala @@ -0,0 +1,24 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.nr.agent.security.instrumentation.play26 + +import play.api.mvc._ + +import javax.inject.Inject +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future + +class SimpleScalaController @Inject()(components: ControllerComponents) extends AbstractController(components) { + + def scalaHello = Action.async { + Future { + Ok("Scala says hello world") + } + } + +} diff --git a/instrumentation-security/play-2.6/src/test/resources/conf/routes b/instrumentation-security/play-2.6/src/test/resources/conf/routes new file mode 100644 index 000000000..7af0d11ef --- /dev/null +++ b/instrumentation-security/play-2.6/src/test/resources/conf/routes @@ -0,0 +1,5 @@ +GET /hello com.nr.agent.security.instrumentation.play26.SimpleJavaController.hello +GET /index com.nr.agent.security.instrumentation.play26.SimpleJavaController.index +GET /simple com.nr.agent.security.instrumentation.play26.SimpleJavaController.simple +GET /scalaHello com.nr.agent.security.instrumentation.play26.SimpleScalaController.scalaHello +POST /post com.nr.agent.security.instrumentation.play26.SimpleJavaController.post(data: String) \ No newline at end of file From 6c0d9aab88ea21b5617d48eec97de2d5e2030f9e Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 15 Feb 2024 18:30:20 +0530 Subject: [PATCH 009/124] Unit Tests for API endpoint support for play-2.13_2.7 --- .../play-2.13_2.7/build.gradle | 47 ++++++++++++ .../play2_7/APIEndpointTest.java | 74 +++++++++++++++++++ .../play2_7/PlayApplicationServerRule.java | 60 +++++++++++++++ .../play2_7/SimpleJavaAction.java | 61 +++++++++++++++ .../play2_7/SimpleJavaController.java | 39 ++++++++++ .../play2_7/SimpleScalaController.scala | 24 ++++++ .../src/test/resources/conf/routes | 5 ++ 7 files changed, 310 insertions(+) create mode 100644 instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/APIEndpointTest.java create mode 100644 instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/PlayApplicationServerRule.java create mode 100644 instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleJavaAction.java create mode 100644 instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleJavaController.java create mode 100644 instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleScalaController.scala create mode 100644 instrumentation-security/play-2.13_2.7/src/test/resources/conf/routes diff --git a/instrumentation-security/play-2.13_2.7/build.gradle b/instrumentation-security/play-2.13_2.7/build.gradle index 670053f82..0fa5fde0a 100644 --- a/instrumentation-security/play-2.13_2.7/build.gradle +++ b/instrumentation-security/play-2.13_2.7/build.gradle @@ -1,3 +1,7 @@ +import play.routes.compiler.InjectedRoutesGenerator$ +import play.routes.compiler.RoutesCompiler +import play.routes.compiler.RoutesCompiler$ + apply plugin: 'scala' scala { @@ -5,12 +9,31 @@ scala { } isScalaProjectEnabled(project, "scala-2.13") +sourceSets.test.scala.srcDir "src/test/java" +sourceSets.test.java.srcDirs = [] + +compileJava.options.bootstrapClasspath = null + +buildscript { + dependencies { + classpath 'com.typesafe.play:routes-compiler_2.13:2.7.3' + } + repositories { + mavenCentral() + } +} + dependencies { implementation(project(":newrelic-security-api")) implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation("org.scala-lang:scala-library:2.13.12") implementation("com.typesafe.play:play_2.13:2.7.3") + testImplementation("com.typesafe.play:routes-compiler_2.13:2.7.3") + testImplementation("com.typesafe.play:play-test_2.13:2.7.3") + testImplementation("com.typesafe.play:play-akka-http-server_2.13:2.7.3") + testImplementation("com.typesafe.play:play-java_2.13:2.7.3") + testImplementation("jakarta.xml.ws:jakarta.xml.ws-api:2.3.3") } jar { @@ -26,6 +49,30 @@ verifyInstrumentation { excludeRegex '.*-[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]{7}$' } +compileTestScala { + def routeFile = file("src/test/resources/conf/routes") + def generatedSourcesDir = layout.buildDirectory.dir("generated/scala") + + options.compilerArgs += '-proc:none' + + inputs.file(routeFile) + localState.register(generatedSourcesDir) + + // this manually compiles the conf/routes file into an Routes.scala file, which is subsequently read on startup by our test application + doFirst { + def RoutesCompiler.RoutesCompilerTask routesCompilerTask = new RoutesCompiler.RoutesCompilerTask( + routeFile, scala.collection.immutable.List$.MODULE$.empty().toSeq(), true, false, false) + RoutesCompiler$.MODULE$.compile(routesCompilerTask, InjectedRoutesGenerator$.MODULE$, generatedSourcesDir.get().asFile) + source generatedSourcesDir + scala.collection.immutable.List$.MODULE$.empty() + } +} + +clean { + // Clean up any residual generated Routes files to avoid duplicate classes + delete 'src/test/scala/router' +} + site { title 'Play' type 'Appserver' diff --git a/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/APIEndpointTest.java b/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/APIEndpointTest.java new file mode 100644 index 000000000..50d2e31b4 --- /dev/null +++ b/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/APIEndpointTest.java @@ -0,0 +1,74 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.nr.agent.security.instrumentation.play2_7; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.security.test.marker.Java17IncompatibleTest; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + +@Category({ Java17IncompatibleTest.class }) +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = { "com.newrelic.agent.security.instrumentation.play2_13" }) +public class APIEndpointTest { + + @ClassRule + public static PlayApplicationServerRule serverRule = new PlayApplicationServerRule(); + + private static final Map expectedMappings = new HashMap<>(); + + @BeforeClass + public static void setupMappings() { + expectedMappings.put("/hello", SimpleJavaController.class.getName() + ".hello"); + expectedMappings.put("/scalaHello", SimpleScalaController.class.getName() + ".scalaHello"); + expectedMappings.put("/post", SimpleJavaController.class.getName() + ".post(data:String)"); + expectedMappings.put("/index", SimpleJavaController.class.getName() + ".index"); + expectedMappings.put("/simple", SimpleJavaController.class.getName() + ".simple"); + } + + @Test + public void testControllerActions() throws IOException { + HttpURLConnection conn = ((HttpURLConnection) serverRule.getEndpoint("/hello").openConnection()); + conn.connect(); + System.out.println(conn.getResponseCode()); + + Set actualMappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertNotNull(actualMappings); + Assert.assertEquals(5, actualMappings.size()); + for (ApplicationURLMapping actualMapping : actualMappings) { + assertMappings(actualMapping); + } + } + + private void assertMappings(ApplicationURLMapping actualMapping){ + Assert.assertNotNull(actualMapping.getPath()); + Assert.assertNotNull(actualMapping.getHandler()); + Assert.assertNotNull(actualMapping.getMethod()); + + String path = actualMapping.getPath(); + String handler = expectedMappings.get(path); + String method = !path.equals("/post") ? "GET" : "POST"; + + Assert.assertEquals(handler, actualMapping.getHandler()); + Assert.assertEquals(method, actualMapping.getMethod()); + } +} \ No newline at end of file diff --git a/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/PlayApplicationServerRule.java b/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/PlayApplicationServerRule.java new file mode 100644 index 000000000..5d551f312 --- /dev/null +++ b/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/PlayApplicationServerRule.java @@ -0,0 +1,60 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.nr.agent.security.instrumentation.play2_7; + +import org.junit.rules.ExternalResource; +import play.Application; +import play.inject.guice.GuiceApplicationBuilder; +import play.test.Helpers; +import play.test.TestServer; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.ServerSocket; +import java.net.URL; + +import static play.inject.Bindings.bind; + +public class PlayApplicationServerRule extends ExternalResource { + private TestServer server; + private int port; + + public PlayApplicationServerRule() { + this.port = getRandomPort(); + } + + @Override + protected void before() throws Throwable { + Application application = new GuiceApplicationBuilder() + .bindings( + bind(SimpleJavaController.class).toSelf().eagerly(), + bind(SimpleScalaController.class).toSelf().eagerly(), + bind(SimpleJavaAction.class).toSelf().eagerly()) + .build(); + + server = Helpers.testServer(port, application); + server.start(); + } + + @Override + protected void after() { + server.stop(); + } + + private int getRandomPort() { + try (ServerSocket socket = new ServerSocket(0)){ + return socket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Unable to allocate ephemeral PORT"); + } + } + + public URL getEndpoint(String path) throws MalformedURLException { + return new URL("http://localhost:" + port + path); + } +} diff --git a/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleJavaAction.java b/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleJavaAction.java new file mode 100644 index 000000000..8f0b6f74b --- /dev/null +++ b/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleJavaAction.java @@ -0,0 +1,61 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.nr.agent.security.instrumentation.play2_7; + + +import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.TimeUnit; +import javax.inject.Inject; + +import play.Logger; +import play.libs.concurrent.Futures; +import play.libs.concurrent.HttpExecutionContext; +import play.mvc.Http; +import play.mvc.Result; +import play.mvc.Results; + +import static play.mvc.Http.Status.GATEWAY_TIMEOUT; + +public class SimpleJavaAction extends play.mvc.Action.Simple { + private final Logger.ALogger logger = Logger.of("application.SimpleJavaAction"); + + private final HttpExecutionContext ec; + private final Futures futures; + + @Inject + public SimpleJavaAction(HttpExecutionContext ec, Futures futures) { + this.ec = ec; + this.futures = futures; + } + + public CompletionStage call(Http.Request req) { + if (logger.isTraceEnabled()) { + logger.trace("call: req = " + req); + } + + return futures.timeout(doCall(req), 1L, TimeUnit.SECONDS).exceptionally(e -> + (Results.status(GATEWAY_TIMEOUT, "No"))); + } + + private CompletionStage doCall(Http.Request req) { + return delegate.call(req).handleAsync((result, e) -> { + if (e != null) { + if (e instanceof CompletionException) { + logger.error("Direct exception " + e.getMessage(), e); + return internalServerError(); + } else { + logger.error("Unknown exception " + e.getMessage(), e); + return internalServerError(); + } + } else { + return result; + } + }, ec.current()); + } +} \ No newline at end of file diff --git a/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleJavaController.java b/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleJavaController.java new file mode 100644 index 000000000..67dd207ac --- /dev/null +++ b/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleJavaController.java @@ -0,0 +1,39 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.nr.agent.security.instrumentation.play2_7; + +import javax.inject.Inject; + +import play.libs.concurrent.HttpExecutionContext; +import play.mvc.Controller; +import play.mvc.Result; +import play.mvc.With; + +@With(SimpleJavaAction.class) +public class SimpleJavaController extends Controller { + private HttpExecutionContext ec; + + @Inject + public SimpleJavaController(HttpExecutionContext ec) { + this.ec = ec; + } + + public Result post(String data) { return ok("Received data: " + data).as("text/plain");} + public Result hello() { + return ok("hello world").as("text/plain"); + } + + public Result index() { + return ok("Index Page").as("text/plain"); + } + + public Result simple() { + return ok("Simple test").as("text/plain"); + } + +} diff --git a/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleScalaController.scala b/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleScalaController.scala new file mode 100644 index 000000000..8f84ab42c --- /dev/null +++ b/instrumentation-security/play-2.13_2.7/src/test/java/com/nr/agent/security/instrumentation/play2_7/SimpleScalaController.scala @@ -0,0 +1,24 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.nr.agent.security.instrumentation.play2_7 + +import play.api.mvc._ + +import javax.inject.Inject +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future + +class SimpleScalaController @Inject()(components: ControllerComponents) extends AbstractController(components) { + + def scalaHello = Action.async { + Future { + Ok("Scala says hello world") + } + } + +} diff --git a/instrumentation-security/play-2.13_2.7/src/test/resources/conf/routes b/instrumentation-security/play-2.13_2.7/src/test/resources/conf/routes new file mode 100644 index 000000000..530d9c58d --- /dev/null +++ b/instrumentation-security/play-2.13_2.7/src/test/resources/conf/routes @@ -0,0 +1,5 @@ +GET /hello com.nr.agent.security.instrumentation.play2_7.SimpleJavaController.hello +GET /index com.nr.agent.security.instrumentation.play2_7.SimpleJavaController.index +GET /simple com.nr.agent.security.instrumentation.play2_7.SimpleJavaController.simple +GET /scalaHello com.nr.agent.security.instrumentation.play2_7.SimpleScalaController.scalaHello +POST /post com.nr.agent.security.instrumentation.play2_7.SimpleJavaController.post(data: String) \ No newline at end of file From c9c7669f27b66a45c7aa6585847b00e4d9f00d33 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 19 Feb 2024 18:34:41 +0530 Subject: [PATCH 010/124] API endpoint support for jetty server --- .../ContextHandler_Instrumentation.java | 11 ++++- .../jetty11/HttpServletHelper.java | 41 ++++++++++++++++++ .../ContextHandler_Instrumentation.java | 13 +++++- .../jetty9/HttpServletHelper.java | 42 +++++++++++++++++++ 4 files changed, 105 insertions(+), 2 deletions(-) diff --git a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/ContextHandler_Instrumentation.java b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/ContextHandler_Instrumentation.java index 734ad779c..6745182db 100644 --- a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/ContextHandler_Instrumentation.java +++ b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/ContextHandler_Instrumentation.java @@ -6,9 +6,11 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.handler.ContextHandler; @Weave(type = MatchType.ExactClass, originalName = "org.eclipse.jetty.server.handler.ContextHandler") -public class ContextHandler_Instrumentation { +public abstract class ContextHandler_Instrumentation { + public abstract ContextHandler.Context getServletContext(); public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) { boolean isServletLockAcquired = acquireServletLockIfPossible(); @@ -27,6 +29,13 @@ public void doHandle(String target, Request baseRequest, HttpServletRequest requ HttpServletHelper.SERVICE_METHOD_NAME); } } + protected void doStart() throws Exception { + try { + Weaver.callOriginal(); + } finally { + HttpServletHelper.gatherURLMappings(getServletContext()); + } + } private boolean acquireServletLockIfPossible() { try { diff --git a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java index c414129f9..cb5cbd66a 100644 --- a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java +++ b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java @@ -4,17 +4,22 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.HttpRequest; import com.newrelic.api.agent.security.schema.SecurityMetaData; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletRegistration; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.util.Arrays; +import java.util.Collection; import java.util.Enumeration; import java.util.Map; @@ -28,6 +33,8 @@ public class HttpServletHelper { public static final String NR_SEC_CUSTOM_ATTRIB_NAME = "SERVLET_LOCK-"; public static final String JETTY_11 = "JETTY-11"; + public static final String WILDCARD = "*"; + public static final String SEPARATOR = "/"; public static void processHttpRequestHeader(HttpServletRequest request, HttpRequest securityRequest) { Enumeration headerNames = request.getHeaderNames(); @@ -193,4 +200,38 @@ public static void postProcessSecurityHook(HttpServletRequest request, HttpServl NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, JETTY_11, e.getMessage()), e, HttpServletHelper.class.getName()); } } + public static void gatherURLMappings(ServletContext servletContext) { + try { + Map servletRegistrations = servletContext.getServletRegistrations(); + getJSPMappings(servletContext, SEPARATOR); + + for (ServletRegistration servletReg : servletRegistrations.values()) { + for (String mapping : servletReg.getMappings()) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, servletReg.getClassName())); + } + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, JETTY_11, e.getMessage()), e, HttpServletHelper.class.getName()); + } + } + + private static void getJSPMappings(ServletContext servletContext, String dir) { + try { + if(dir.endsWith(SEPARATOR)){ + Collection resourcePaths = servletContext.getResourcePaths(dir); + for (String path : resourcePaths) { + if(path.endsWith(SEPARATOR)) { + getJSPMappings(servletContext, path); + } + else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); + } + } + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, JETTY_11, e.getMessage()), e, HttpServletHelper.class.getName()); + } + } } diff --git a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/ContextHandler_Instrumentation.java b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/ContextHandler_Instrumentation.java index 10e5b07ac..e8e17d5a6 100644 --- a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/ContextHandler_Instrumentation.java +++ b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/ContextHandler_Instrumentation.java @@ -4,12 +4,15 @@ import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.handler.ContextHandler; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Weave(type = MatchType.ExactClass, originalName = "org.eclipse.jetty.server.handler.ContextHandler") -public class ContextHandler_Instrumentation { +public abstract class ContextHandler_Instrumentation { + + public abstract ContextHandler.Context getServletContext(); public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) { boolean isServletLockAcquired = acquireServletLockIfPossible(); @@ -29,6 +32,14 @@ public void doHandle(String target, Request baseRequest, HttpServletRequest requ } } + protected void doStart() throws Exception { + try { + Weaver.callOriginal(); + } finally { + HttpServletHelper.gatherURLMappings(getServletContext()); + } + } + private boolean acquireServletLockIfPossible() { try { return HttpServletHelper.acquireServletLockIfPossible(); diff --git a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java index 03ac12d08..457ac48bd 100644 --- a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java +++ b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java @@ -4,7 +4,9 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.HttpRequest; import com.newrelic.api.agent.security.schema.SecurityMetaData; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; @@ -12,9 +14,12 @@ import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; +import javax.servlet.ServletContext; +import javax.servlet.ServletRegistration; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Arrays; +import java.util.Collection; import java.util.Enumeration; import java.util.Map; @@ -27,6 +32,9 @@ public class HttpServletHelper { public static final String SERVICE_ASYNC_METHOD_NAME = "handleAsync"; public static final String NR_SEC_CUSTOM_ATTRIB_NAME = "SERVLET_LOCK-"; public static final String JETTY_9 = "JETTY-9"; + private static final String SEPARATOR = "/"; + private static final String WILDCARD = "*"; + public static void processHttpRequestHeader(HttpServletRequest request, HttpRequest securityRequest) { Enumeration headerNames = request.getHeaderNames(); @@ -194,4 +202,38 @@ public static void postProcessSecurityHook(HttpServletRequest request, HttpServl NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, JETTY_9, e.getMessage()), e, HttpServletHelper.class.getName()); } } + public static void gatherURLMappings(ServletContext servletContext) { + try { + Map servletRegistrations = servletContext.getServletRegistrations(); + getJSPMappings(servletContext, SEPARATOR); + + for (ServletRegistration servletReg : servletRegistrations.values()) { + for (String mapping : servletReg.getMappings()) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, servletReg.getClassName())); + } + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, JETTY_9, e.getMessage()), e, HttpServletHelper.class.getName()); + } + } + + private static void getJSPMappings(ServletContext servletContext, String dir) { + try { + if(dir.endsWith(SEPARATOR)){ + Collection resourcePaths = servletContext.getResourcePaths(dir); + for (String path : resourcePaths) { + if(path.endsWith(SEPARATOR)) { + getJSPMappings(servletContext, path); + } + else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); + } + } + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, JETTY_9, e.getMessage()), e, HttpServletHelper.class.getName()); + } + } } From 02b623feb53b0d80cc4ea414d46f38968e78271c Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 19 Feb 2024 19:20:36 +0530 Subject: [PATCH 011/124] Unit tests for jetty server API endpoint support --- .../instrumentation/jetty11/ServerTest.java | 48 +++++++++++++++---- .../instrumentation/jetty9/ServerTest.java | 40 ++++++++++++---- 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java b/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java index 71a73dd60..78269c9d6 100644 --- a/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java +++ b/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java @@ -5,8 +5,10 @@ import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.agent.security.instrumentation.jetty11.HttpServletHelper; @@ -14,9 +16,11 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.junit.After; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; @@ -29,8 +33,10 @@ import java.net.HttpURLConnection; import java.net.ServerSocket; import java.net.URL; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -42,6 +48,12 @@ public class ServerTest { private Server server; + private static final Map actualMappings = new HashMap<>(); + @BeforeClass + public static void addMappings() { + actualMappings.put("/servlet/*", MyServlet.class.getName()); + actualMappings.put("/", ServletHandler.Default404Servlet.class.getName()); + } @After public void teardown() throws Exception { if (server.isRunning()) { @@ -184,21 +196,30 @@ public void testHandle3() throws Exception { Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getRequest().getContentType()); } + @Test + public void testAPIEndpoint () throws Exception { + start(); + + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertEquals(2, mappings.size()); + for (ApplicationURLMapping mapping : mappings) { + Assert.assertNotNull(mapping); + + Assert.assertNotNull(mapping.getHandler()); + Assert.assertNotNull(mapping.getPath()); + Assert.assertNotNull(mapping.getMethod()); + + Assert.assertEquals(actualMappings.get(mapping.getPath()), mapping.getHandler()); + Assert.assertEquals("*", mapping.getMethod()); + } + } private void start() throws Exception { server = new Server(PORT); - ServletHolder holder = new ServletHolder( - new HttpServlet() { - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) { - resp.setContentType("text/plain;charset=utf-8"); - resp.setStatus(HttpServletResponse.SC_OK); - } - } - ); + ServletHolder holder = new ServletHolder(new MyServlet()); ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS); handler.setContextPath("/"); server.setHandler(handler); - handler.addServlet(holder, "/*"); + handler.addServlet(holder, "/servlet/*"); server.start(); } @@ -252,3 +273,10 @@ private static int getRandomPort() { } } } +class MyServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + resp.setContentType("text/plain;charset=utf-8"); + resp.setStatus(HttpServletResponse.SC_OK); + } +} \ No newline at end of file diff --git a/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java b/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java index 4ff76d7cc..e7f236937 100644 --- a/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java +++ b/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java @@ -5,8 +5,10 @@ import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.agent.security.instrumentation.jetty9.HttpServletHelper; @@ -31,6 +33,7 @@ import java.net.URL; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -184,21 +187,30 @@ public void testHandle3() throws Exception { Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getRequest().getContentType()); } + @Test + public void testAPIEndpoint () throws Exception { + start(); + + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertEquals(1, mappings.size()); + + for (ApplicationURLMapping mapping : mappings) { + Assert.assertNotNull(mapping); + Assert.assertNotNull(mapping.getHandler()); + Assert.assertNotNull(mapping.getPath()); + Assert.assertNotNull(mapping.getMethod()); + Assert.assertEquals(MyServlet.class.getName(), mapping.getHandler()); + Assert.assertEquals("/servlet/*", mapping.getPath()); + Assert.assertEquals("*", mapping.getMethod()); + } + } private void start() throws Exception { server = new Server(PORT); - ServletHolder holder = new ServletHolder( - new HttpServlet() { - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) { - resp.setContentType("text/plain;charset=utf-8"); - resp.setStatus(HttpServletResponse.SC_OK); - } - } - ); + ServletHolder holder = new ServletHolder(new MyServlet()); ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS); handler.setContextPath("/"); server.setHandler(handler); - handler.addServlet(holder, "/*"); + handler.addServlet(holder, "/servlet/*"); server.start(); } @@ -252,3 +264,11 @@ private static int getRandomPort() { } } } + +class MyServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + resp.setContentType("text/plain;charset=utf-8"); + resp.setStatus(HttpServletResponse.SC_OK); + } +} \ No newline at end of file From 2f99ae6c4e9f0ba8d700d4039a005ef55881e1af Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 21 Feb 2024 11:37:53 +0530 Subject: [PATCH 012/124] Spray Http incoming request interception --- .../spray-http-1.3.1/build.gradle | 34 +++++++++++++++++++ .../spray/routing/SprayRoutingHttpServer.java | 26 ++++++++++++++ settings.gradle | 1 + 3 files changed, 61 insertions(+) create mode 100644 instrumentation-security/spray-http-1.3.1/build.gradle create mode 100644 instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java diff --git a/instrumentation-security/spray-http-1.3.1/build.gradle b/instrumentation-security/spray-http-1.3.1/build.gradle new file mode 100644 index 000000000..23f9007c1 --- /dev/null +++ b/instrumentation-security/spray-http-1.3.1/build.gradle @@ -0,0 +1,34 @@ +apply plugin: 'scala' + +isScalaProjectEnabled(project, "scala-2.10") + +sourceSets.test.scala.srcDir "src/test/java" +sourceSets.test.java.srcDirs = [] + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.spray-http-1.3.1' } +} + +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("org.scala-lang:scala-library:2.10.7") + implementation("io.spray:spray-routing_2.10:1.3.3") + implementation("com.typesafe.akka:akka-actor_2.10:2.3.14") + +} + +verifyInstrumentation { + passesOnly('io.spray:spray-routing_2.11:[1.3.1,)') { + implementation("com.typesafe.akka:akka-actor_2.11:2.3.14") + } + passesOnly('io.spray:spray-routing_2.10:[1.3.1,)') { + implementation("com.typesafe.akka:akka-actor_2.10:2.3.14") + } +} + +site { + title 'Spray-http' + type 'Messaging' +} \ No newline at end of file diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java new file mode 100644 index 000000000..399da2f42 --- /dev/null +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java @@ -0,0 +1,26 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package spray.routing; +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +import scala.Function1; +import scala.PartialFunction; + +@Weave(type = MatchType.ExactClass, originalName = "spray.routing.HttpServiceBase$class") +public class SprayRoutingHttpServer { + + @Trace(dispatcher = true) + public static final void runSealedRoute$1(final HttpServiceBase $this, final RequestContext ctx, final PartialFunction sealedExceptionHandler$1, final Function1 sealedRoute$1) { + System.out.println("Request Intercepted!!! ctx:"+ctx.request().method().name()+":"+ctx.request().protocol().value()+":"+ctx.request().uri().toString()+":"+ctx.request().headers()); + Weaver.callOriginal(); + } + +} diff --git a/settings.gradle b/settings.gradle index 932f59700..643529a47 100644 --- a/settings.gradle +++ b/settings.gradle @@ -178,3 +178,4 @@ include 'instrumentation:grpc-1.40.0' //include 'instrumentation:jetty-12' //include 'instrumentation:mule-3.7' //include 'instrumentation:mule-3.6' +include 'instrumentation:spray-http-1.3.1' From 15b91fb5aeff863eadc2c9011f11f1b422b3d52c Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 21 Feb 2024 16:25:58 +0530 Subject: [PATCH 013/124] Spray Http request body interception & request header extraction --- .../src/main/scala/spray/SprayHttpUtils.java | 134 ++++++++++++++++++ .../spray/routing/SprayRoutingHttpServer.java | 15 +- .../agent/security/schema/StringUtils.java | 43 ++++++ 3 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java new file mode 100644 index 000000000..a4b3ad623 --- /dev/null +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java @@ -0,0 +1,134 @@ +package spray; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.RXSSOperation; +import com.newrelic.api.agent.security.schema.policy.AgentPolicy; +import com.newrelic.api.agent.security.utils.logging.LogLevel; +import scala.collection.immutable.List; +import spray.http.*; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +public class SprayHttpUtils { + + public static final String QUESTION_MARK = "?"; + + private static final String X_FORWARDED_FOR = "x-forwarded-for"; + public static final String SPRAY_HTTP_1_3_1 = "SPRAY-HTTP-1.3.1"; + + public static String getNrSecCustomAttribName() { + return "SPRAY-HTTP-" + Thread.currentThread().getId(); + } + + public static void preProcessRequestHook(HttpRequest request) { + try { + if (!NewRelicSecurity.isHookProcessingActive()) { + return; + } + SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + + com.newrelic.api.agent.security.schema.HttpRequest securityRequest = securityMetaData.getRequest(); + if (securityRequest.isRequestParsed()) { + return; + } + + AgentMetaData securityAgentMetaData = securityMetaData.getMetaData(); + securityRequest.setMethod(request.method().name()); + securityRequest.setProtocol(request.protocol().value()); + securityRequest.setUrl(processURL(request.uri())); + securityRequest.setServerPort(request.uri().effectivePort()); + processHttpRequestHeader(request.headers(), securityRequest); + if (!request.entity().isEmpty()) { + if (request.entity() instanceof HttpEntity.NonEmpty) { + securityRequest.setContentType(((HttpEntity.NonEmpty) request.entity()).contentType().value()); + } + securityRequest.setBody(new StringBuilder(request.entity().data().asString(StandardCharsets.UTF_8))); + } + + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(trace, 2, trace.length)); + securityRequest.setRequestParsed(true); + } catch (Exception e){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + e.printStackTrace(); + } + } + + private static void processHttpRequestHeader(List headers, com.newrelic.api.agent.security.schema.HttpRequest securityRequest) { + headers.foreach( element -> { + String headerKey = element.lowercaseName(); + String headerValue = element.value(); + boolean takeNextValue = false; + AgentPolicy agentPolicy = NewRelicSecurity.getAgent().getCurrentPolicy(); + AgentMetaData agentMetaData = NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData(); + if (agentPolicy != null + && agentPolicy.getProtectionMode().getEnabled() + && agentPolicy.getProtectionMode().getIpBlocking().getEnabled() + && agentPolicy.getProtectionMode().getIpBlocking().getIpDetectViaXFF() + && X_FORWARDED_FOR.equals(headerKey)) { + takeNextValue = true; + } else if (ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.equals(headerKey)) { + // TODO: May think of removing this intermediate obj and directly create K2 Identifier. + NewRelicSecurity.getAgent().getSecurityMetaData().setFuzzRequestIdentifier(ServletHelper.parseFuzzRequestIdentifierHeader(headerValue)); + } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, headerValue); + } + if (takeNextValue) { + agentMetaData.setClientDetectedFromXFF(true); + securityRequest.setClientIP(headerValue); + agentMetaData.getIps() + .add(securityRequest.getClientIP()); + } + securityRequest.getHeaders().put(headerKey, headerValue); + + return null; + }); + } + + private static String processURL(Uri uri) { + String path = uri.path().toString(); + String suri = uri.toString(); + String queryString = StringUtils.substringAfter(suri, QUESTION_MARK); + if(StringUtils.isBlank(queryString)){ + return path; + } else { + return path + QUESTION_MARK + queryString; + } + } + + public static void postProcessSecurityHook(HttpResponse httpResponse, String className, String methodName) { + try { + if (!NewRelicSecurity.isHookProcessingActive() + ) { + return; + } + //Add request URI hash to low severity event filter + LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); + + if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { + RXSSOperation rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest(), + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse(), + className, methodName); + NewRelicSecurity.getAgent().registerOperation(rxssOperation); + } + ServletHelper.tmpFileCleanUp(NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getTempFiles()); + } catch (Throwable e) { + e.printStackTrace(); + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + } + } +} diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java index 399da2f42..997927ef4 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java @@ -7,12 +7,15 @@ package spray.routing; import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import scala.Function1; import scala.PartialFunction; +import spray.SprayHttpUtils; +import spray.http.HttpEntity; @Weave(type = MatchType.ExactClass, originalName = "spray.routing.HttpServiceBase$class") public class SprayRoutingHttpServer { @@ -20,7 +23,17 @@ public class SprayRoutingHttpServer { @Trace(dispatcher = true) public static final void runSealedRoute$1(final HttpServiceBase $this, final RequestContext ctx, final PartialFunction sealedExceptionHandler$1, final Function1 sealedRoute$1) { System.out.println("Request Intercepted!!! ctx:"+ctx.request().method().name()+":"+ctx.request().protocol().value()+":"+ctx.request().uri().toString()+":"+ctx.request().headers()); - Weaver.callOriginal(); + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribName()); + if (isLockAcquired) { + SprayHttpUtils.preProcessRequestHook(ctx.request()); + } + try { + Weaver.callOriginal(); + } finally { + if(isLockAcquired){ + GenericHelper.releaseLock(SprayHttpUtils.getNrSecCustomAttribName()); + } + } } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/StringUtils.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/StringUtils.java index 08cfc96a5..aeee5c8a7 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/StringUtils.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/StringUtils.java @@ -181,6 +181,49 @@ public static String substringBeforeLast(final String str, final String separato return str.substring(0, pos); } + /** + *

Gets the substring after the first occurrence of a separator. + * The separator is not returned.

+ * + *

A {@code null} string input will return {@code null}. + * An empty ("") string input will return the empty string. + * A {@code null} separator will return the empty string if the + * input string is not {@code null}.

+ * + *

If nothing is found, the empty string is returned.

+ * + *
+     * StringUtils.substringAfter(null, *)      = null
+     * StringUtils.substringAfter("", *)        = ""
+     * StringUtils.substringAfter(*, null)      = ""
+     * StringUtils.substringAfter("abc", "a")   = "bc"
+     * StringUtils.substringAfter("abcba", "b") = "cba"
+     * StringUtils.substringAfter("abc", "c")   = ""
+     * StringUtils.substringAfter("abc", "d")   = ""
+     * StringUtils.substringAfter("abc", "")    = "abc"
+     * 
+ * + * @param str the String to get a substring from, may be null + * @param separator the String to search for, may be null + * @return the substring after the first occurrence of the separator, + * {@code null} if null String input + * @since 2.0 + */ + public static String substringAfter(final String str, final String separator) { + if (isEmpty(str)) { + return str; + } + if (separator == null) { + return EMPTY; + } + final int pos = str.indexOf(separator); + if (pos == INDEX_NOT_FOUND) { + return EMPTY; + } + return str.substring(pos + separator.length()); + } + + /** *

Gets the substring after the last occurrence of a separator. * The separator is not returned.

From 2b276ae6e58088e33ff50e4c6792426fe0e012f2 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 21 Feb 2024 16:26:19 +0530 Subject: [PATCH 014/124] Spray Http response body interception & rxss event generation --- .../SprayToResponseMarshallingContext.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java new file mode 100644 index 000000000..b9e8f1354 --- /dev/null +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java @@ -0,0 +1,55 @@ + +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package spray.httpx.marshalling; + +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import scala.collection.JavaConversions; +import spray.SprayHttpUtils; +import spray.http.HttpEntity; +import spray.http.HttpHeader; +import spray.http.HttpResponse; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +@Weave(type = MatchType.Interface, originalName = "spray.httpx.marshalling.ToResponseMarshallingContext") +public class SprayToResponseMarshallingContext { + + @Trace(async = true) + public void marshalTo(HttpResponse httpResponse) { + System.out.println("Response handling!!! : "+httpResponse.status().value()); + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribName()); + try { + if (isLockAcquired && httpResponse.entity().nonEmpty()) { + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(new StringBuilder(httpResponse.entity().data().asString(StandardCharsets.UTF_8))); + if (httpResponse.entity() instanceof HttpEntity.NonEmpty) { + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(((HttpEntity.NonEmpty) httpResponse.entity()).contentType().value()); + } + SprayHttpUtils.postProcessSecurityHook(httpResponse, this.getClass().getName(), "marshalTo"); + } + } catch (Exception e){ + e.printStackTrace(); + } + try { + Weaver.callOriginal(); + } finally { + if(isLockAcquired){ + GenericHelper.releaseLock(SprayHttpUtils.getNrSecCustomAttribName()); + } + } + } + +} From c51f67a94a2471b12a3299bdab55a16336e1f819 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 22 Feb 2024 10:46:37 +0530 Subject: [PATCH 015/124] Spray Http request header extraction --- .../src/main/scala/spray/SprayHttpUtils.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java index a4b3ad623..429ec5314 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java @@ -11,6 +11,7 @@ import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; +import scala.collection.Iterator; import scala.collection.immutable.List; import spray.http.*; @@ -63,7 +64,9 @@ public static void preProcessRequestHook(HttpRequest request) { } private static void processHttpRequestHeader(List headers, com.newrelic.api.agent.security.schema.HttpRequest securityRequest) { - headers.foreach( element -> { + Iterator headerIterator = headers.iterator(); + while (headerIterator.hasNext()){ + HttpHeader element = headerIterator.next(); String headerKey = element.lowercaseName(); String headerValue = element.value(); boolean takeNextValue = false; @@ -89,9 +92,7 @@ private static void processHttpRequestHeader(List headers, com.newre .add(securityRequest.getClientIP()); } securityRequest.getHeaders().put(headerKey, headerValue); - - return null; - }); + } } private static String processURL(Uri uri) { From d25b90b1ca263dba7bb220f6915c60c8f0ddb772 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 22 Feb 2024 10:47:28 +0530 Subject: [PATCH 016/124] Fix incorrect protocol --- .../src/main/scala/spray/SprayHttpUtils.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java index 429ec5314..876e705b6 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java @@ -29,6 +29,16 @@ public static String getNrSecCustomAttribName() { return "SPRAY-HTTP-" + Thread.currentThread().getId(); } + private static String getProtocol(String value) { + if(StringUtils.containsIgnoreCase(value, "https")){ + return "https"; + } else if (StringUtils.containsIgnoreCase(value, "http")) { + return "http"; + } else { + return value; + } + } + public static void preProcessRequestHook(HttpRequest request) { try { if (!NewRelicSecurity.isHookProcessingActive()) { @@ -43,7 +53,7 @@ public static void preProcessRequestHook(HttpRequest request) { AgentMetaData securityAgentMetaData = securityMetaData.getMetaData(); securityRequest.setMethod(request.method().name()); - securityRequest.setProtocol(request.protocol().value()); + securityRequest.setProtocol(getProtocol(request.protocol().value())); securityRequest.setUrl(processURL(request.uri())); securityRequest.setServerPort(request.uri().effectivePort()); processHttpRequestHeader(request.headers(), securityRequest); From e93efbed1046c76e870a2f4a54de9fc11694b460 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 22 Feb 2024 11:17:59 +0530 Subject: [PATCH 017/124] add protocol from incoming request uri --- .../spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java index 876e705b6..d5ec98ebc 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java @@ -53,7 +53,7 @@ public static void preProcessRequestHook(HttpRequest request) { AgentMetaData securityAgentMetaData = securityMetaData.getMetaData(); securityRequest.setMethod(request.method().name()); - securityRequest.setProtocol(getProtocol(request.protocol().value())); + securityRequest.setProtocol(request.uri().scheme()); securityRequest.setUrl(processURL(request.uri())); securityRequest.setServerPort(request.uri().effectivePort()); processHttpRequestHeader(request.headers(), securityRequest); From da892ab4736b1067b305cf422530495d20242819 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 22 Feb 2024 11:53:00 +0530 Subject: [PATCH 018/124] set tracing header into meta deta --- .../src/main/scala/spray/SprayHttpUtils.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java index d5ec98ebc..24e090ed4 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java @@ -12,11 +12,16 @@ import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; import scala.collection.Iterator; +import scala.collection.Seq$; import scala.collection.immutable.List; +import scala.collection.immutable.List$; +import scala.collection.mutable.Seq; import spray.http.*; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Map; public class SprayHttpUtils { @@ -57,6 +62,9 @@ public static void preProcessRequestHook(HttpRequest request) { securityRequest.setUrl(processURL(request.uri())); securityRequest.setServerPort(request.uri().effectivePort()); processHttpRequestHeader(request.headers(), securityRequest); + + securityMetaData.setTracingHeaderValue(getTraceHeader(securityRequest.getHeaders())); + if (!request.entity().isEmpty()) { if (request.entity() instanceof HttpEntity.NonEmpty) { securityRequest.setContentType(((HttpEntity.NonEmpty) request.entity()).contentType().value()); @@ -73,6 +81,17 @@ public static void preProcessRequestHook(HttpRequest request) { } } + public static String getTraceHeader(Map headers) { + String data = StringUtils.EMPTY; + if (headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER) || headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())) { + data = headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER); + if (data == null || data.trim().isEmpty()) { + data = headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()); + } + } + return data; + } + private static void processHttpRequestHeader(List headers, com.newrelic.api.agent.security.schema.HttpRequest securityRequest) { Iterator headerIterator = headers.iterator(); while (headerIterator.hasNext()){ From f6795a8c6b8d855a6a67b72dba8a3080d58aa746 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 22 Feb 2024 17:23:13 +0530 Subject: [PATCH 019/124] updated locking attribute for spray response --- .../spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java | 3 +++ .../httpx/marshalling/SprayToResponseMarshallingContext.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java index 24e090ed4..4a5ca91af 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java @@ -33,6 +33,9 @@ public class SprayHttpUtils { public static String getNrSecCustomAttribName() { return "SPRAY-HTTP-" + Thread.currentThread().getId(); } + public static String getNrSecCustomAttribNameForResponse() { + return "SPRAY-HTTP-RXSS" + Thread.currentThread().getId(); + } private static String getProtocol(String value) { if(StringUtils.containsIgnoreCase(value, "https")){ diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java index b9e8f1354..95e45ca86 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java @@ -31,7 +31,7 @@ public class SprayToResponseMarshallingContext { @Trace(async = true) public void marshalTo(HttpResponse httpResponse) { System.out.println("Response handling!!! : "+httpResponse.status().value()); - boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribName()); + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribNameForResponse()); try { if (isLockAcquired && httpResponse.entity().nonEmpty()) { NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(new StringBuilder(httpResponse.entity().data().asString(StandardCharsets.UTF_8))); @@ -47,7 +47,7 @@ public void marshalTo(HttpResponse httpResponse) { Weaver.callOriginal(); } finally { if(isLockAcquired){ - GenericHelper.releaseLock(SprayHttpUtils.getNrSecCustomAttribName()); + GenericHelper.releaseLock(SprayHttpUtils.getNrSecCustomAttribNameForResponse()); } } } From 4a07678a353b59a9b4475e6873384a9cb9e612aa Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 22 Feb 2024 18:15:28 +0530 Subject: [PATCH 020/124] Added Logging message constants --- .../agent/security/instrumentation/helpers/GenericHelper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java index 4a5e28067..d22cd3346 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java @@ -18,6 +18,7 @@ public class GenericHelper { public static final String URI_EXCEPTION_MESSAGE = "Instrumentation library: %s , error while extracting URI : %s"; public static final String ERROR_GENERATING_HTTP_REQUEST = "Instrumentation library: %s , error while generating HTTP request : %s"; public static final String ERROR_PARSING_HTTP_REQUEST_DATA = "Instrumentation library: %s , error while parsing HTTP request data : %s"; + public static final String ERROR_PARSING_HTTP_RESPONSE = "Instrumentation library: %s , error while parsing HTTP Response data : %s"; public static boolean skipExistsEvent() { if (!(NewRelicSecurity.getAgent().getCurrentPolicy().getVulnerabilityScan().getEnabled() && From 0fb20896ec202429f9943f3724ef3a9be1284803 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 22 Feb 2024 18:17:03 +0530 Subject: [PATCH 021/124] code cleanup --- .../src/main/scala/spray/SprayHttpUtils.java | 19 +------------------ .../SprayToResponseMarshallingContext.java | 10 ++-------- .../spray/routing/SprayRoutingHttpServer.java | 2 -- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java index 4a5ca91af..ceca8c914 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java @@ -12,14 +12,10 @@ import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; import scala.collection.Iterator; -import scala.collection.Seq$; import scala.collection.immutable.List; -import scala.collection.immutable.List$; -import scala.collection.mutable.Seq; import spray.http.*; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.Arrays; import java.util.Map; @@ -37,16 +33,6 @@ public static String getNrSecCustomAttribNameForResponse() { return "SPRAY-HTTP-RXSS" + Thread.currentThread().getId(); } - private static String getProtocol(String value) { - if(StringUtils.containsIgnoreCase(value, "https")){ - return "https"; - } else if (StringUtils.containsIgnoreCase(value, "http")) { - return "http"; - } else { - return value; - } - } - public static void preProcessRequestHook(HttpRequest request) { try { if (!NewRelicSecurity.isHookProcessingActive()) { @@ -80,7 +66,6 @@ public static void preProcessRequestHook(HttpRequest request) { securityRequest.setRequestParsed(true); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); - e.printStackTrace(); } } @@ -129,8 +114,7 @@ private static void processHttpRequestHeader(List headers, com.newre private static String processURL(Uri uri) { String path = uri.path().toString(); - String suri = uri.toString(); - String queryString = StringUtils.substringAfter(suri, QUESTION_MARK); + String queryString = StringUtils.substringAfter(uri.toString(), QUESTION_MARK); if(StringUtils.isBlank(queryString)){ return path; } else { @@ -155,7 +139,6 @@ public static void postProcessSecurityHook(HttpResponse httpResponse, String cla } ServletHelper.tmpFileCleanUp(NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getTempFiles()); } catch (Throwable e) { - e.printStackTrace(); if (e instanceof NewRelicSecurityException) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); throw e; diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java index 95e45ca86..41d03a37e 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/httpx/marshalling/SprayToResponseMarshallingContext.java @@ -11,26 +11,20 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import scala.collection.JavaConversions; import spray.SprayHttpUtils; import spray.http.HttpEntity; -import spray.http.HttpHeader; import spray.http.HttpResponse; - -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; @Weave(type = MatchType.Interface, originalName = "spray.httpx.marshalling.ToResponseMarshallingContext") public class SprayToResponseMarshallingContext { @Trace(async = true) public void marshalTo(HttpResponse httpResponse) { - System.out.println("Response handling!!! : "+httpResponse.status().value()); boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribNameForResponse()); try { if (isLockAcquired && httpResponse.entity().nonEmpty()) { @@ -41,7 +35,7 @@ public void marshalTo(HttpResponse httpResponse) { SprayHttpUtils.postProcessSecurityHook(httpResponse, this.getClass().getName(), "marshalTo"); } } catch (Exception e){ - e.printStackTrace(); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_PARSING_HTTP_RESPONSE, SprayHttpUtils.SPRAY_HTTP_1_3_1, e.getMessage()), e, this.getClass().getName()); } try { Weaver.callOriginal(); diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java index 997927ef4..7fa994c8d 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java @@ -15,14 +15,12 @@ import scala.Function1; import scala.PartialFunction; import spray.SprayHttpUtils; -import spray.http.HttpEntity; @Weave(type = MatchType.ExactClass, originalName = "spray.routing.HttpServiceBase$class") public class SprayRoutingHttpServer { @Trace(dispatcher = true) public static final void runSealedRoute$1(final HttpServiceBase $this, final RequestContext ctx, final PartialFunction sealedExceptionHandler$1, final Function1 sealedRoute$1) { - System.out.println("Request Intercepted!!! ctx:"+ctx.request().method().name()+":"+ctx.request().protocol().value()+":"+ctx.request().uri().toString()+":"+ctx.request().headers()); boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribName()); if (isLockAcquired) { SprayHttpUtils.preProcessRequestHook(ctx.request()); From e662a44bfe0d12a98beae32aef8b8bf97f03414c Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 23 Feb 2024 11:37:33 +0530 Subject: [PATCH 022/124] updated comment --- .../src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java index 5aa9083d8..3eac30459 100644 --- a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java @@ -123,7 +123,7 @@ public static void preProcessHttpRequest (Boolean isServletLockAcquired, HttpReq try { queryString = httpRequest.getUri().rawQueryString().get(); } catch (NoSuchElementException ignored) { - // ignore NoSuchElementException – there is no value present in rawQueryString + // ignore NoSuchElementException there is no value present in rawQueryString } finally { if (queryString != null && !queryString.trim().isEmpty()) { securityRequest.setUrl(securityRequest.getUrl() + QUESTION_MARK + queryString); From 6d993814b827c876adafbd3ca60f6defec9d0089 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 23 Feb 2024 12:39:38 +0530 Subject: [PATCH 023/124] Extract server port info for spray can --- .../spray-can-1.3.1/build.gradle | 30 ++++++++++++++ .../scala/spray/can/Http_Instrumentation.java | 40 +++++++++++++++++++ settings.gradle | 1 + 3 files changed, 71 insertions(+) create mode 100644 instrumentation-security/spray-can-1.3.1/build.gradle create mode 100644 instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/Http_Instrumentation.java diff --git a/instrumentation-security/spray-can-1.3.1/build.gradle b/instrumentation-security/spray-can-1.3.1/build.gradle new file mode 100644 index 000000000..777a3cbb1 --- /dev/null +++ b/instrumentation-security/spray-can-1.3.1/build.gradle @@ -0,0 +1,30 @@ +apply plugin: 'scala' + +isScalaProjectEnabled(project, "scala-2.10") + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.spray-can-1.3.1' } +} + +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("org.scala-lang:scala-library:2.10.7") + implementation("io.spray:spray-can_2.10:1.3.3") + implementation("com.typesafe.akka:akka-actor_2.10:2.3.14") +} + +verifyInstrumentation { + passesOnly('io.spray:spray-can_2.11:[1.3.1,)'){ + implementation("com.typesafe.akka:akka-actor_2.11:2.3.14") + } + passesOnly('io.spray:spray-can_2.10:[1.3.1,)'){ + implementation("com.typesafe.akka:akka-actor_2.10:2.3.14") + } +} + +site { + title 'Spray-can' + type 'Messaging' +} \ No newline at end of file diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/Http_Instrumentation.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/Http_Instrumentation.java new file mode 100644 index 000000000..aef111d4a --- /dev/null +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/Http_Instrumentation.java @@ -0,0 +1,40 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package spray.can; + +import java.net.InetSocketAddress; + +import akka.actor.ActorRef; +import akka.io.Inet; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import scala.Option; +import scala.collection.immutable.Traversable; +import spray.can.server.ServerSettings; +import spray.io.ServerSSLEngineProvider; + +@Weave(originalName = "spray.can.Http") +public class Http_Instrumentation { + + @Weave(originalName = "spray.can.Http$Bind") + public static class Bind { + + public Bind(final ActorRef listener, final InetSocketAddress endpoint, final int backlog, + final Traversable options, final Option settings, + final ServerSSLEngineProvider sslEngineProvider) { + Weaver.callOriginal(); + NewRelicSecurity.getAgent().setApplicationConnectionConfig(endpoint.getPort(), "http"); + +// setServerInfo("spray-can HTTP", ManifestUtils.getVersionFromManifest(getClass(), +// "spray-can", "1.3.1-1.3.3")); + } + + } + +} diff --git a/settings.gradle b/settings.gradle index 643529a47..9015cbcb0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -178,4 +178,5 @@ include 'instrumentation:grpc-1.40.0' //include 'instrumentation:jetty-12' //include 'instrumentation:mule-3.7' //include 'instrumentation:mule-3.6' +include 'instrumentation:spray-can-1.3.1' include 'instrumentation:spray-http-1.3.1' From af845623c01c3e345627b6c1189e297ea6afede1 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 23 Feb 2024 14:23:23 +0530 Subject: [PATCH 024/124] unit tests for spray-http support --- .../spray-http-1.3.1/build.gradle | 2 +- .../instrumentation/spray/http/SprayTest.java | 159 ++++++++++++++++++ .../spray/http/HttpServer.scala | 43 +++++ 3 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 instrumentation-security/spray-http-1.3.1/src/test/java/com/nr/agent/security/instrumentation/spray/http/SprayTest.java create mode 100644 instrumentation-security/spray-http-1.3.1/src/test/scala/com/nr/agent/security/instrumentation/spray/http/HttpServer.scala diff --git a/instrumentation-security/spray-http-1.3.1/build.gradle b/instrumentation-security/spray-http-1.3.1/build.gradle index 23f9007c1..14d61a161 100644 --- a/instrumentation-security/spray-http-1.3.1/build.gradle +++ b/instrumentation-security/spray-http-1.3.1/build.gradle @@ -16,7 +16,7 @@ dependencies { implementation("org.scala-lang:scala-library:2.10.7") implementation("io.spray:spray-routing_2.10:1.3.3") implementation("com.typesafe.akka:akka-actor_2.10:2.3.14") - + testImplementation("io.spray:spray-can_2.10:1.3.3") } verifyInstrumentation { diff --git a/instrumentation-security/spray-http-1.3.1/src/test/java/com/nr/agent/security/instrumentation/spray/http/SprayTest.java b/instrumentation-security/spray-http-1.3.1/src/test/java/com/nr/agent/security/instrumentation/spray/http/SprayTest.java new file mode 100644 index 000000000..a96b77eda --- /dev/null +++ b/instrumentation-security/spray-http-1.3.1/src/test/java/com/nr/agent/security/instrumentation/spray/http/SprayTest.java @@ -0,0 +1,159 @@ +package com.nr.agent.security.instrumentation.spray.http; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.agent.security.introspec.SecurityIntrospector; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; +import com.newrelic.api.agent.security.schema.operation.RXSSOperation; +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.ServerSocket; +import java.net.URL; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = { "spray", "scala" }) +public class SprayTest { + + @ClassRule + public static HttpServer server = HttpServer$.MODULE$.apply(getRandomPort()); + private static int port; + + @Test + public void testGet() throws IOException { + makeRequest("GET", StringUtils.EMPTY); + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertNotNull(operations); + Assert.assertEquals(1, operations.size()); + + RXSSOperation operation = (RXSSOperation) operations.get(0); + Assert.assertNotNull("No target operation detected", operation); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); + Assert.assertEquals("Wrong method name detected", "marshalTo", operation.getMethodName()); + + Assert.assertNotNull("Empty request detected", operation.getRequest()); + Assert.assertEquals("Wrong Protocol detected", "http", operation.getRequest().getProtocol()); + Assert.assertEquals("Wrong port detected", port, operation.getRequest().getServerPort()); + Assert.assertEquals("Wrong Content-type detected", StringUtils.EMPTY, operation.getRequest().getContentType()); + + Assert.assertNotNull("Empty response detected", operation.getResponse()); + Assert.assertEquals("Wrong port detected", "testing API", operation.getResponse().getResponseBody().toString()); + Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getResponse().getResponseContentType()); + + } + @Test + public void testPost() throws IOException { + makeRequest("POST", StringUtils.EMPTY); + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertNotNull(operations); + Assert.assertEquals(1, operations.size()); + + RXSSOperation operation = (RXSSOperation) operations.get(0); + Assert.assertNotNull("No target operation detected", operation); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); + Assert.assertEquals("Wrong method name detected", "marshalTo", operation.getMethodName()); + + Assert.assertNotNull("Empty request detected", operation.getRequest()); + Assert.assertEquals("Wrong Protocol detected", "http", operation.getRequest().getProtocol()); + Assert.assertEquals("Wrong port detected", port, operation.getRequest().getServerPort()); + Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getRequest().getContentType()); + Assert.assertEquals("Wrong Content-type detected", "data", operation.getRequest().getBody().toString()); + + Assert.assertNotNull("Empty response detected", operation.getResponse()); + Assert.assertEquals("Wrong port detected", "testing API", operation.getResponse().getResponseBody().toString()); + Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getResponse().getResponseContentType()); + + } + + @Test + public void testWithCSECHeader() throws IOException { + String headerValue = String.valueOf(UUID.randomUUID()); + makeRequest("GET", headerValue); + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertNotNull(operations); + Assert.assertEquals(1, operations.size()); + + RXSSOperation operation = (RXSSOperation) operations.get(0); + Assert.assertNotNull("No target operation detected", operation); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); + Assert.assertEquals("Wrong method name detected", "marshalTo", operation.getMethodName()); + + Assert.assertNotNull("Empty request detected", operation.getRequest()); + Assert.assertEquals("Wrong Protocol detected", "http", operation.getRequest().getProtocol()); + Assert.assertEquals("Wrong port detected", port, operation.getRequest().getServerPort()); + Assert.assertEquals("Wrong Content-type detected", StringUtils.EMPTY, operation.getRequest().getContentType()); + + Assert.assertNotNull("Empty response detected", operation.getResponse()); + Assert.assertEquals("Wrong port detected", "testing API", operation.getResponse().getResponseBody().toString()); + Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getResponse().getResponseContentType()); + + Map headers = operation.getRequest().getHeaders(); + Assert.assertTrue( + String.format("Missing header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), + headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), + headerValue, + headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + ); + Assert.assertTrue( + String.format("Missing header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), + headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), + headerValue, + headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) + ); + Assert.assertTrue( + String.format("Missing header: %s", GenericHelper.CSEC_PARENT_ID), + headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase()) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", GenericHelper.CSEC_PARENT_ID), + headerValue, + headers.get(GenericHelper.CSEC_PARENT_ID.toLowerCase()) + ); + } + + private static int getRandomPort(){ + try (ServerSocket socket = new ServerSocket(0)){ + return port = socket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Unable to allocate ephemeral port"); + } + } + + private void makeRequest(String method, String csecHeaders) throws IOException { + String ENDPOINT = String.format("http://localhost:%d/test", port); + HttpURLConnection conn = (HttpURLConnection) new URL(ENDPOINT).openConnection(); + conn.setRequestMethod(method); + conn.setDoOutput(true); + conn.setRequestProperty("Content-Type", "text/plain"); + if (method.equalsIgnoreCase("POST")) { + conn.getOutputStream().write("data".getBytes()); + } + if (!csecHeaders.isEmpty()) { + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, csecHeaders); + conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, csecHeaders); + conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, csecHeaders); + } + conn.connect(); + System.out.println("response status: " + conn.getResponseCode()); + } +} diff --git a/instrumentation-security/spray-http-1.3.1/src/test/scala/com/nr/agent/security/instrumentation/spray/http/HttpServer.scala b/instrumentation-security/spray-http-1.3.1/src/test/scala/com/nr/agent/security/instrumentation/spray/http/HttpServer.scala new file mode 100644 index 000000000..972012aea --- /dev/null +++ b/instrumentation-security/spray-http-1.3.1/src/test/scala/com/nr/agent/security/instrumentation/spray/http/HttpServer.scala @@ -0,0 +1,43 @@ +package com.nr.agent.security.instrumentation.spray.http + +import akka.actor.{Actor, ActorContext, ActorRef, ActorSystem, Props} +import akka.io.IO +import akka.pattern._ +import akka.util.Timeout +import org.junit.rules.ExternalResource +import spray.can.Http +import spray.routing.{HttpService, RequestContext, Route} + +import scala.concurrent.duration._ +import scala.concurrent.{Await, Future} +import scala.language.postfixOps + +class HttpServer(port: Int) extends ExternalResource { + private implicit val system: ActorSystem = ActorSystem() + private implicit val timeout: Timeout = 3 seconds + + private val handler: ActorRef = system.actorOf(Props[MainActor], name = "handler") + + private def start(port: Int): Future[Any] = Await.ready( + IO(Http) ? Http.Bind(handler, "localhost", port), + timeout.duration + ) + + private def stop(): Unit = { + IO(Http) ? Http.CloseAll + system.stop(handler) + system.shutdown() + } + override def before(): Unit = start(port) + override def after(): Unit = stop() +} + +object HttpServer { + def apply(port: Int) = new HttpServer(port) +} + +class MainActor extends Actor with HttpService { + def route: Route = path("test") { (ctx: RequestContext) => ctx.complete("testing API")} + def actorRefFactory: ActorContext = context + def receive: Receive = runRoute(route) +} \ No newline at end of file From da213dd8eba7b493d3ed463468370e20aa076f5e Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 23 Feb 2024 15:25:03 +0530 Subject: [PATCH 025/124] added applicationUUID to ApplicationURLMappings Json --- .../agent/security/instrumentator/utils/AgentUtils.java | 1 + .../models/javaagent/ApplicationURLMappings.java | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/AgentUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/AgentUtils.java index 0aabb9ac1..da5c72381 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/AgentUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/AgentUtils.java @@ -669,6 +669,7 @@ private void applyNRPolicyOverride() { public static void sendApplicationURLMappings() { //TODO mappings to be send once new mappings are discovered, after startup. ApplicationURLMappings applicationURLMappings = new ApplicationURLMappings(URLMappingsHelper.getApplicationURLMappings()); + applicationURLMappings.setApplicationUUID(AgentInfo.getInstance().getApplicationUUID()); logger.logInit(LogLevel.INFO, String.format("Collected application url mappings %s", applicationURLMappings), Agent.class.getName()); EventSendPool.getInstance().sendEvent(applicationURLMappings); } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationURLMappings.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationURLMappings.java index 6dec9b791..a65c8177c 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationURLMappings.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationURLMappings.java @@ -7,6 +7,7 @@ public class ApplicationURLMappings extends AgentBasicInfo{ + private String applicationUUID; private Set mappings; public ApplicationURLMappings(Set mappings) { @@ -25,4 +26,12 @@ public void setMappings(Set mappings) { public String toString() { return JsonConverter.toJSON(this); } + + public String getApplicationUUID() { + return applicationUUID; + } + + public void setApplicationUUID(String applicationUUID) { + this.applicationUUID = applicationUUID; + } } From b3ca3a5d7806365f2bea82090ab7bfb487f287f3 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 26 Feb 2024 11:33:01 +0530 Subject: [PATCH 026/124] Spray server request instrumentation --- .../main/scala/spray/can/SprayHttpUtils.java | 150 ++++++++++++++++++ .../ServerFrontend_Instrumentation.java | 34 ++++ 2 files changed, 184 insertions(+) create mode 100644 instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java create mode 100644 instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/server/ServerFrontend_Instrumentation.java diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java new file mode 100644 index 000000000..8978f78e2 --- /dev/null +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java @@ -0,0 +1,150 @@ +package spray.can; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.RXSSOperation; +import com.newrelic.api.agent.security.schema.policy.AgentPolicy; +import com.newrelic.api.agent.security.utils.logging.LogLevel; +import scala.collection.Iterator; +import scala.collection.immutable.List; +import spray.http.*; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Map; + +public class SprayHttpUtils { + + public static final String QUESTION_MARK = "?"; + + private static final String X_FORWARDED_FOR = "x-forwarded-for"; + public static final String SPRAY_HTTP_1_3_1 = "SPRAY-CAN-1.3.1"; + + public static String getNrSecCustomAttribName() { + return "SPRAY-HTTP-" + Thread.currentThread().getId(); + } + public static String getNrSecCustomAttribNameForResponse() { + return "SPRAY-CAN-RXSS" + Thread.currentThread().getId(); + } + + public static void preProcessRequestHook(HttpRequest request) { + try { + if (!NewRelicSecurity.isHookProcessingActive()) { + return; + } + SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + + com.newrelic.api.agent.security.schema.HttpRequest securityRequest = securityMetaData.getRequest(); + if (securityRequest.isRequestParsed()) { + return; + } + + AgentMetaData securityAgentMetaData = securityMetaData.getMetaData(); + securityRequest.setMethod(request.method().name()); + securityRequest.setProtocol(request.uri().scheme()); + securityRequest.setUrl(processURL(request.uri())); + securityRequest.setServerPort(request.uri().effectivePort()); + processHttpRequestHeader(request.headers(), securityRequest); + + securityMetaData.setTracingHeaderValue(getTraceHeader(securityRequest.getHeaders())); + + if (!request.entity().isEmpty()) { + if (request.entity() instanceof HttpEntity.NonEmpty) { + securityRequest.setContentType(((HttpEntity.NonEmpty) request.entity()).contentType().value()); + } + securityRequest.setBody(new StringBuilder(request.entity().data().asString(StandardCharsets.UTF_8))); + } + + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(trace, 2, trace.length)); + securityRequest.setRequestParsed(true); + } catch (Exception e){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + } + } + + public static String getTraceHeader(Map headers) { + String data = StringUtils.EMPTY; + if (headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER) || headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())) { + data = headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER); + if (data == null || data.trim().isEmpty()) { + data = headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()); + } + } + return data; + } + + private static void processHttpRequestHeader(List headers, com.newrelic.api.agent.security.schema.HttpRequest securityRequest) { + Iterator headerIterator = headers.iterator(); + while (headerIterator.hasNext()){ + HttpHeader element = headerIterator.next(); + String headerKey = element.lowercaseName(); + String headerValue = element.value(); + boolean takeNextValue = false; + AgentPolicy agentPolicy = NewRelicSecurity.getAgent().getCurrentPolicy(); + AgentMetaData agentMetaData = NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData(); + if (agentPolicy != null + && agentPolicy.getProtectionMode().getEnabled() + && agentPolicy.getProtectionMode().getIpBlocking().getEnabled() + && agentPolicy.getProtectionMode().getIpBlocking().getIpDetectViaXFF() + && X_FORWARDED_FOR.equals(headerKey)) { + takeNextValue = true; + } else if (ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.equals(headerKey)) { + // TODO: May think of removing this intermediate obj and directly create K2 Identifier. + NewRelicSecurity.getAgent().getSecurityMetaData().setFuzzRequestIdentifier(ServletHelper.parseFuzzRequestIdentifierHeader(headerValue)); + } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, headerValue); + } + if (takeNextValue) { + agentMetaData.setClientDetectedFromXFF(true); + securityRequest.setClientIP(headerValue); + agentMetaData.getIps() + .add(securityRequest.getClientIP()); + } + securityRequest.getHeaders().put(headerKey, headerValue); + } + } + + private static String processURL(Uri uri) { + String path = uri.path().toString(); + String queryString = StringUtils.substringAfter(uri.toString(), QUESTION_MARK); + if(StringUtils.isBlank(queryString)){ + return path; + } else { + return path + QUESTION_MARK + queryString; + } + } + + public static void postProcessSecurityHook(HttpResponse httpResponse, String className, String methodName) { + try { + if (!NewRelicSecurity.isHookProcessingActive() + ) { + return; + } + //Add request URI hash to low severity event filter + LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); + + if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { + RXSSOperation rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest(), + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse(), + className, methodName); + NewRelicSecurity.getAgent().registerOperation(rxssOperation); + } + ServletHelper.tmpFileCleanUp(NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getTempFiles()); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + } + } +} diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/server/ServerFrontend_Instrumentation.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/server/ServerFrontend_Instrumentation.java new file mode 100644 index 000000000..16eb7b704 --- /dev/null +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/server/ServerFrontend_Instrumentation.java @@ -0,0 +1,34 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package spray.can.server; + +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import spray.can.SprayHttpUtils; +import spray.http.HttpRequest; + +@Weave(originalName = "spray.can.server.ServerFrontend$$anon$2$$anon$1") +public class ServerFrontend_Instrumentation { + @Trace(dispatcher = true) + public void spray$can$server$ServerFrontend$$anon$$anon$$openNewRequest(final HttpRequest request, + final boolean closeAfterResponseCompletion, final RequestState state) { + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribName()); + if (isLockAcquired) { + SprayHttpUtils.preProcessRequestHook(request); + } + try { + Weaver.callOriginal(); + } finally { + if(isLockAcquired){ + GenericHelper.releaseLock(SprayHttpUtils.getNrSecCustomAttribName()); + } + } + } +} From a898d4b34a41626cf3a1ffbaea0c9ff5e9c2d31e Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 26 Feb 2024 12:57:05 +0530 Subject: [PATCH 027/124] Spray-Can response body interception & rxss event generation --- .../main/scala/spray/can/SprayHttpUtils.java | 2 +- .../ResponseRendering_Instrumentation.java | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java index 8978f78e2..d195edb89 100644 --- a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java @@ -27,7 +27,7 @@ public class SprayHttpUtils { public static final String SPRAY_HTTP_1_3_1 = "SPRAY-CAN-1.3.1"; public static String getNrSecCustomAttribName() { - return "SPRAY-HTTP-" + Thread.currentThread().getId(); + return "SPRAY-CAN-" + Thread.currentThread().getId(); } public static String getNrSecCustomAttribNameForResponse() { return "SPRAY-CAN-RXSS" + Thread.currentThread().getId(); diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java new file mode 100644 index 000000000..391ce8a19 --- /dev/null +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java @@ -0,0 +1,44 @@ +package spray.can.rendering; + +import akka.event.LoggingAdapter; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.utils.logging.LogLevel; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import spray.can.SprayHttpUtils; +import spray.http.HttpEntity; +import spray.http.HttpResponse; +import spray.http.Rendering; + +import java.nio.charset.StandardCharsets; + +@Weave(originalName = "spray.can.rendering.ResponseRenderingComponent$class") +public class ResponseRendering_Instrumentation { + private static boolean renderResponse$1(ResponseRenderingComponent component, HttpResponse response, + Rendering rendering, ResponsePartRenderingContext context, LoggingAdapter adapter) { + + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribNameForResponse()); + try { + if (isLockAcquired && response.entity().nonEmpty()) { + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(new StringBuilder(response.entity().data().asString(StandardCharsets.UTF_8))); + if (response.entity() instanceof HttpEntity.NonEmpty) { + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(((HttpEntity.NonEmpty) response.entity()).contentType().value()); + } + SprayHttpUtils.postProcessSecurityHook(response, ResponseRendering_Instrumentation.class.getName(), "renderResponse$1"); + } + } catch (Exception e){ + e.printStackTrace(); + } + boolean result; + try { + result = Weaver.callOriginal(); + } finally { + if(isLockAcquired){ + GenericHelper.releaseLock(SprayHttpUtils.getNrSecCustomAttribNameForResponse()); + } + } + return result; + } + +} From a4562e945c84bef3a6ef89ae561b72ea4ce76dbf Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 26 Feb 2024 13:02:14 +0530 Subject: [PATCH 028/124] add critical logging for spray-can instrumentation --- .../src/main/scala/spray/can/SprayHttpUtils.java | 10 +++++----- .../rendering/ResponseRendering_Instrumentation.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java index d195edb89..bd9c9f361 100644 --- a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java @@ -24,7 +24,7 @@ public class SprayHttpUtils { public static final String QUESTION_MARK = "?"; private static final String X_FORWARDED_FOR = "x-forwarded-for"; - public static final String SPRAY_HTTP_1_3_1 = "SPRAY-CAN-1.3.1"; + public static final String SPRAY_CAN_1_3_1 = "SPRAY-CAN-1.3.1"; public static String getNrSecCustomAttribName() { return "SPRAY-CAN-" + Thread.currentThread().getId(); @@ -65,7 +65,7 @@ public static void preProcessRequestHook(HttpRequest request) { securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(trace, 2, trace.length)); securityRequest.setRequestParsed(true); } catch (Exception e){ - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, SPRAY_CAN_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); } } @@ -140,11 +140,11 @@ public static void postProcessSecurityHook(HttpResponse httpResponse, String cla ServletHelper.tmpFileCleanUp(NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getTempFiles()); } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, SPRAY_CAN_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); throw e; } - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRAY_HTTP_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRAY_CAN_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRAY_CAN_1_3_1, e.getMessage()), e, SprayHttpUtils.class.getName()); } } } diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java index 391ce8a19..ccfccafa1 100644 --- a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/rendering/ResponseRendering_Instrumentation.java @@ -28,7 +28,7 @@ public class ResponseRendering_Instrumentation { SprayHttpUtils.postProcessSecurityHook(response, ResponseRendering_Instrumentation.class.getName(), "renderResponse$1"); } } catch (Exception e){ - e.printStackTrace(); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_PARSING_HTTP_RESPONSE, SprayHttpUtils.SPRAY_CAN_1_3_1, e.getMessage()), e, ResponseRendering_Instrumentation.class.getName()); } boolean result; try { From f47cd6930a280cfef4ebdc57870126c7aea937d9 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 26 Feb 2024 13:06:19 +0530 Subject: [PATCH 029/124] removed Weaver callOriginal() from constructor --- .../src/main/scala/spray/can/Http_Instrumentation.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/Http_Instrumentation.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/Http_Instrumentation.java index aef111d4a..8bde104f4 100644 --- a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/Http_Instrumentation.java +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/Http_Instrumentation.java @@ -13,7 +13,6 @@ import akka.io.Inet; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.weaver.Weave; -import com.newrelic.api.agent.weaver.Weaver; import scala.Option; import scala.collection.immutable.Traversable; import spray.can.server.ServerSettings; @@ -28,11 +27,7 @@ public static class Bind { public Bind(final ActorRef listener, final InetSocketAddress endpoint, final int backlog, final Traversable options, final Option settings, final ServerSSLEngineProvider sslEngineProvider) { - Weaver.callOriginal(); NewRelicSecurity.getAgent().setApplicationConnectionConfig(endpoint.getPort(), "http"); - -// setServerInfo("spray-can HTTP", ManifestUtils.getVersionFromManifest(getClass(), -// "spray-can", "1.3.1-1.3.3")); } } From a401e553698b7b67eb7fe91fc45aed98802a28b7 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 26 Feb 2024 14:31:50 +0530 Subject: [PATCH 030/124] Fix for NR-232224 Provided fix for API endpoint not detected, when http-method is empty --- .../reactive/result/method/SpringHelper.java | 11 ++++++--- .../web/servlet/handler310/SpringHelper.java | 9 ++++++-- .../web/servlet/handler530/SpringHelper.java | 23 ++++++++++++++----- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/instrumentation-security/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SpringHelper.java b/instrumentation-security/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SpringHelper.java index 58f358731..2f5b15824 100644 --- a/instrumentation-security/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SpringHelper.java +++ b/instrumentation-security/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SpringHelper.java @@ -9,13 +9,18 @@ import java.lang.reflect.Method; public class SpringHelper { + private static final String WILDCARD = "*"; public static void gatherURLMappings(T mapping, Method method){ try { RequestMappingInfo mappingInfo = (RequestMappingInfo) mapping; PatternsRequestCondition patternsCondition = mappingInfo.getPatternsCondition(); - if(patternsCondition!=null) { - for (RequestMethod requestMethod : mappingInfo.getMethodsCondition().getMethods()) { - for (PathPattern url : patternsCondition.getPatterns()) { + if (patternsCondition != null) { + for (PathPattern url : patternsCondition.getPatterns()) { + if (mappingInfo.getMethodsCondition().getMethods().isEmpty()) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, url.getPatternString(), method.getDeclaringClass().getName())); + continue; + } + for (RequestMethod requestMethod : mappingInfo.getMethodsCondition().getMethods()) { URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(requestMethod.name(), url.getPatternString(), method.getDeclaringClass().getName())); } } diff --git a/instrumentation-security/spring-webmvc-3.1.0/src/main/java/org/springframework/web/servlet/handler310/SpringHelper.java b/instrumentation-security/spring-webmvc-3.1.0/src/main/java/org/springframework/web/servlet/handler310/SpringHelper.java index bff8969bc..09ee44f0b 100644 --- a/instrumentation-security/spring-webmvc-3.1.0/src/main/java/org/springframework/web/servlet/handler310/SpringHelper.java +++ b/instrumentation-security/spring-webmvc-3.1.0/src/main/java/org/springframework/web/servlet/handler310/SpringHelper.java @@ -9,13 +9,18 @@ import java.lang.reflect.Method; public class SpringHelper { + private static final String WILDCARD = "*"; public static void gatherURLMappings(T mapping, Method method){ try { RequestMappingInfo mappingInfo = (RequestMappingInfo) mapping; PatternsRequestCondition patternsCondition = mappingInfo.getPatternsCondition(); if (patternsCondition != null) { - for (RequestMethod requestMethod : mappingInfo.getMethodsCondition().getMethods()) { - for (String url : patternsCondition.getPatterns()) { + for (String url : patternsCondition.getPatterns()) { + if (mappingInfo.getMethodsCondition().getMethods().isEmpty()) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, url, method.getDeclaringClass().getName())); + continue; + } + for (RequestMethod requestMethod : mappingInfo.getMethodsCondition().getMethods()) { URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(requestMethod.name(), url, method.getDeclaringClass().getName())); } } diff --git a/instrumentation-security/spring-webmvc-5.3.0/src/main/java/org/springframework/web/servlet/handler530/SpringHelper.java b/instrumentation-security/spring-webmvc-5.3.0/src/main/java/org/springframework/web/servlet/handler530/SpringHelper.java index f40be47a1..b75150c15 100644 --- a/instrumentation-security/spring-webmvc-5.3.0/src/main/java/org/springframework/web/servlet/handler530/SpringHelper.java +++ b/instrumentation-security/spring-webmvc-5.3.0/src/main/java/org/springframework/web/servlet/handler530/SpringHelper.java @@ -11,20 +11,31 @@ import java.lang.reflect.Method; public class SpringHelper { + private static final String WILDCARD = "*"; public static void gatherURLMappings(T mapping, Method method){ try { RequestMappingInfo mappingInfo = (RequestMappingInfo) mapping; PatternsRequestCondition patternsCondition = mappingInfo.getPatternsCondition(); PathPatternsRequestCondition pathPatternsCondition = mappingInfo.getPathPatternsCondition(); - for (RequestMethod requestMethod : mappingInfo.getMethodsCondition().getMethods()) { - if (patternsCondition != null) { - for (String url : patternsCondition.getPatterns()) { + if (patternsCondition != null) { + for (String url : patternsCondition.getPatterns()) { + if(mappingInfo.getMethodsCondition().getMethods().isEmpty()){ + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, url, method.getDeclaringClass().getName())); + continue; + } + for (RequestMethod requestMethod : mappingInfo.getMethodsCondition().getMethods()){ URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(requestMethod.name(), url, method.getDeclaringClass().getName())); } } - else if (pathPatternsCondition != null) { - for (PathPattern url : pathPatternsCondition.getPatterns()) { - if (url != null) { + } + else if (pathPatternsCondition != null) { + for (PathPattern url : pathPatternsCondition.getPatterns()) { + if (url != null) { + if(mappingInfo.getMethodsCondition().getMethods().isEmpty()){ + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, url.getPatternString(), method.getDeclaringClass().getName())); + continue; + } + for (RequestMethod requestMethod : mappingInfo.getMethodsCondition().getMethods()){ URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(requestMethod.name(), url.getPatternString(), method.getDeclaringClass().getName())); } } From c4750fd757b010a6ae5db29363507e9afa588749 Mon Sep 17 00:00:00 2001 From: Monu Lakshkar Date: Mon, 26 Feb 2024 16:24:08 +0530 Subject: [PATCH 031/124] gRPC: Added reason in the critical logs fuzz request failed --- .../grpc1220/processor/GrpcRequestProcessor.java | 10 +++++----- .../grpc140/processor/GrpcRequestProcessor.java | 10 +++++----- .../grpc1400/processor/GrpcRequestProcessor.java | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/processor/GrpcRequestProcessor.java b/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/processor/GrpcRequestProcessor.java index b81f9444b..2964fb0bd 100644 --- a/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/processor/GrpcRequestProcessor.java +++ b/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/processor/GrpcRequestProcessor.java @@ -10,7 +10,7 @@ import java.util.concurrent.Future; public class GrpcRequestProcessor implements Callable { - public static final String CALL_FAILED_REQUEST_S_REASON = "Call failed : request %s reason : "; + public static final String CALL_FAILED_REQUEST_S_REASON = "Call failed : request %s reason : %s "; private ControlCommandDto controlCommandDto; private int repeatCount; private static final int MAX_REPETITION = 3; @@ -31,18 +31,18 @@ public static void executeGrpcRequest(ControlCommandDto controlCommandDto) { try { Object futureResult = future.get(); if (futureResult instanceof Throwable) { - NewRelicSecurity.getAgent().log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean()), (Throwable) futureResult, GrpcClient.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean(), ((Throwable) futureResult).getMessage()), (Throwable) futureResult, GrpcClient.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.WARNING, - String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId()), + String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId(), ((Throwable) futureResult).getMessage()), (Throwable) futureResult, GrpcClient.class.getName()); GrpcClientRequestReplayHelper.getInstance().addFuzzFailEventToQueue(controlCommandDto.getRequestBean(), (Throwable) futureResult); } else { GrpcClientRequestReplayHelper.getInstance().getPendingIds().remove(controlCommandDto.getId()); } } catch (Throwable e) { - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean()), e, GrpcRequestProcessor.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean(), e.getMessage()), e, GrpcRequestProcessor.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, - String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId()), + String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId(), e.getMessage()), e, GrpcRequestProcessor.class.getName()); GrpcClientRequestReplayHelper.getInstance().addFuzzFailEventToQueue(controlCommandDto.getRequestBean(), e); } diff --git a/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/processor/GrpcRequestProcessor.java b/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/processor/GrpcRequestProcessor.java index 242b46e43..b42863147 100644 --- a/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/processor/GrpcRequestProcessor.java +++ b/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/processor/GrpcRequestProcessor.java @@ -10,7 +10,7 @@ import java.util.concurrent.Future; public class GrpcRequestProcessor implements Callable { - public static final String CALL_FAILED_REQUEST_S_REASON = "Call failed : request %s reason : "; + public static final String CALL_FAILED_REQUEST_S_REASON = "Call failed : request %s reason : %s "; private ControlCommandDto controlCommandDto; private int repeatCount; private static final int MAX_REPETITION = 3; @@ -31,18 +31,18 @@ public static void executeGrpcRequest(ControlCommandDto controlCommandDto) { try { Object futureResult = future.get(); if (futureResult instanceof Throwable) { - NewRelicSecurity.getAgent().log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean()), (Throwable) futureResult, GrpcClient.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean(), ((Throwable) futureResult).getMessage()), (Throwable) futureResult, GrpcClient.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.WARNING, - String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId()), + String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId(), ((Throwable) futureResult).getMessage()), (Throwable) futureResult, GrpcClient.class.getName()); GrpcClientRequestReplayHelper.getInstance().addFuzzFailEventToQueue(controlCommandDto.getRequestBean(), (Throwable) futureResult); } else { GrpcClientRequestReplayHelper.getInstance().getPendingIds().remove(controlCommandDto.getId()); } } catch (Throwable e) { - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean()), e, GrpcRequestProcessor.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean(), e.getMessage()), e, GrpcRequestProcessor.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, - String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId()), + String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId(), e.getMessage()), e, GrpcRequestProcessor.class.getName()); GrpcClientRequestReplayHelper.getInstance().addFuzzFailEventToQueue(controlCommandDto.getRequestBean(), e); } diff --git a/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/processor/GrpcRequestProcessor.java b/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/processor/GrpcRequestProcessor.java index f9321adad..8d232c7e6 100644 --- a/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/processor/GrpcRequestProcessor.java +++ b/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/processor/GrpcRequestProcessor.java @@ -10,7 +10,7 @@ import java.util.concurrent.Future; public class GrpcRequestProcessor implements Callable { - public static final String CALL_FAILED_REQUEST_S_REASON = "Call failed : request %s reason : "; + public static final String CALL_FAILED_REQUEST_S_REASON = "Call failed : request %s reason : %s "; private ControlCommandDto controlCommandDto; private int repeatCount; private static final int MAX_REPETITION = 3; @@ -31,18 +31,18 @@ public static void executeGrpcRequest(ControlCommandDto controlCommandDto) { try { Object futureResult = future.get(); if (futureResult instanceof Throwable) { - NewRelicSecurity.getAgent().log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean()), (Throwable) futureResult, GrpcClient.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean(), ((Throwable) futureResult).getMessage()), (Throwable) futureResult, GrpcClient.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.WARNING, - String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId()), + String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId(), ((Throwable) futureResult).getMessage()), (Throwable) futureResult, GrpcClient.class.getName()); GrpcClientRequestReplayHelper.getInstance().addFuzzFailEventToQueue(controlCommandDto.getRequestBean(), (Throwable) futureResult); } else { GrpcClientRequestReplayHelper.getInstance().getPendingIds().remove(controlCommandDto.getId()); } } catch (Throwable e) { - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean()), e, GrpcRequestProcessor.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getRequestBean(), e.getMessage()), e, GrpcRequestProcessor.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, - String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId()), + String.format(CALL_FAILED_REQUEST_S_REASON, controlCommandDto.getId(), e.getMessage()), e, GrpcRequestProcessor.class.getName()); GrpcClientRequestReplayHelper.getInstance().addFuzzFailEventToQueue(controlCommandDto.getRequestBean(), e); } From 5c86ae60158243aaeee788d74ab5aa70903776c1 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 26 Feb 2024 16:54:09 +0530 Subject: [PATCH 032/124] Spray client outgoing request interception Co-authored-by: Lovesh Baya --- .../spray-client/build.gradle | 27 +++++ .../spray/client/SprayUtils.java | 10 ++ .../client/SendReceive_Instrumentation.java | 101 ++++++++++++++++++ settings.gradle | 1 + 4 files changed, 139 insertions(+) create mode 100644 instrumentation-security/spray-client/build.gradle create mode 100644 instrumentation-security/spray-client/src/main/scala/com/newrelic/agent/security/instrumentation/spray/client/SprayUtils.java create mode 100644 instrumentation-security/spray-client/src/main/scala/spray/client/SendReceive_Instrumentation.java diff --git a/instrumentation-security/spray-client/build.gradle b/instrumentation-security/spray-client/build.gradle new file mode 100644 index 000000000..f71ab7b45 --- /dev/null +++ b/instrumentation-security/spray-client/build.gradle @@ -0,0 +1,27 @@ +apply plugin: 'scala' + +isScalaProjectEnabled(project, "scala-2.10") + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.spray-client' } +} + +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("org.scala-lang:scala-library:2.10.7") + implementation("io.spray:spray-client_2.10:1.3.3") + testImplementation("com.typesafe.akka:akka-actor_2.10:2.3.14") + testImplementation("io.spray:spray-can_2.10:1.3.3") +} + +verifyInstrumentation { + passesOnly('io.spray:spray-client_2.11:[1.3.1,)') + passesOnly('io.spray:spray-client_2.10:[1.3.1,)') +} + +site { + title 'Spray-can client' + type 'Messaging' +} \ No newline at end of file diff --git a/instrumentation-security/spray-client/src/main/scala/com/newrelic/agent/security/instrumentation/spray/client/SprayUtils.java b/instrumentation-security/spray-client/src/main/scala/com/newrelic/agent/security/instrumentation/spray/client/SprayUtils.java new file mode 100644 index 000000000..81344b72a --- /dev/null +++ b/instrumentation-security/spray-client/src/main/scala/com/newrelic/agent/security/instrumentation/spray/client/SprayUtils.java @@ -0,0 +1,10 @@ +package com.newrelic.agent.security.instrumentation.spray.client; + +public class SprayUtils { + private static final String NR_SEC_OPERATION_LOCK = "OPERATION_LOCK_SPRAY_CAN_CLIENT-"; + public static final String METHOD_SEND_RECEIVE = "sendReceive"; + public static final String SPRAY_CLIENT = "SPRAY-CLIENT"; + public static String getNrSecCustomAttribName() { + return NR_SEC_OPERATION_LOCK + Thread.currentThread().getId(); + } +} diff --git a/instrumentation-security/spray-client/src/main/scala/spray/client/SendReceive_Instrumentation.java b/instrumentation-security/spray-client/src/main/scala/spray/client/SendReceive_Instrumentation.java new file mode 100644 index 000000000..35e4d6a1a --- /dev/null +++ b/instrumentation-security/spray-client/src/main/scala/spray/client/SendReceive_Instrumentation.java @@ -0,0 +1,101 @@ +package spray.client; + +import com.newrelic.agent.security.instrumentation.spray.client.SprayUtils; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.SSRFOperation; +import com.newrelic.api.agent.security.utils.logging.LogLevel; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import scala.concurrent.Future; +import spray.http.HttpRequest; +import spray.http.HttpResponse; + +import java.net.URI; + +@Weave(type = MatchType.Interface, originalName = "spray.client.pipelining$$anonfun$sendReceive$1") +public class SendReceive_Instrumentation { + + public final Future apply(HttpRequest request) { + boolean isLockAcquired = acquireLockIfPossible(); + AbstractOperation operation = null; + // Preprocess Phase + if (isLockAcquired) { + operation = preprocessSecurityHook(request); + } + + Future returnCode; + try { + returnCode = Weaver.callOriginal(); + } finally { + if (isLockAcquired) { + releaseLock(); + } + } + registerExitOperation(isLockAcquired, operation); + return returnCode; + } + + private void releaseLock() { + try { + GenericHelper.releaseLock(SprayUtils.getNrSecCustomAttribName()); + } catch (Throwable ignored) { + } + } + + private boolean acquireLockIfPossible() { + try { + return GenericHelper.acquireLockIfPossible(SprayUtils.getNrSecCustomAttribName()); + } catch (Throwable ignored) { + } + return false; + } + + private AbstractOperation preprocessSecurityHook(HttpRequest httpRequest) { + try { + SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + if (!NewRelicSecurity.isHookProcessingActive() || securityMetaData.getRequest().isEmpty()) { + return null; + } + + // Generate required URL + URI methodURI = null; + String uri = null; + try { + methodURI = new URI(httpRequest.uri().toString()); + uri = methodURI.toString(); + if (methodURI == null) { + return null; + } + } catch (Exception ignored){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.URI_EXCEPTION_MESSAGE, SprayUtils.SPRAY_CLIENT, ignored.getMessage()), ignored, this.getClass().getName()); + return null; + } + return new SSRFOperation(uri, this.getClass().getName(), SprayUtils.METHOD_SEND_RECEIVE); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, SprayUtils.SPRAY_CLIENT, e.getMessage()), e, this.getClass().getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SprayUtils.SPRAY_CLIENT, e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SprayUtils.SPRAY_CLIENT, e.getMessage()), e, this.getClass().getName()); + } + return null; + } + private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e) { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, SprayUtils.SPRAY_CLIENT, e.getMessage()), e, this.getClass().getName()); + } + } +} + diff --git a/settings.gradle b/settings.gradle index 9015cbcb0..225a8556a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -180,3 +180,4 @@ include 'instrumentation:grpc-1.40.0' //include 'instrumentation:mule-3.6' include 'instrumentation:spray-can-1.3.1' include 'instrumentation:spray-http-1.3.1' +include 'instrumentation:spray-client' From bda3948f3b561dc41b81e7080cadfe27a7bcdc25 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 26 Feb 2024 17:09:24 +0530 Subject: [PATCH 033/124] Spray client adding CSEC headers to outgoing request Co-authored-by: Lovesh Baya --- .../spray/client/OutboundRequest.scala | 25 ++++++++++++++ .../client/SendReceive_Instrumentation.java | 33 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 instrumentation-security/spray-client/src/main/scala/com/newrelic/agent/security/instrumentation/spray/client/OutboundRequest.scala diff --git a/instrumentation-security/spray-client/src/main/scala/com/newrelic/agent/security/instrumentation/spray/client/OutboundRequest.scala b/instrumentation-security/spray-client/src/main/scala/com/newrelic/agent/security/instrumentation/spray/client/OutboundRequest.scala new file mode 100644 index 000000000..fd0aaf790 --- /dev/null +++ b/instrumentation-security/spray-client/src/main/scala/com/newrelic/agent/security/instrumentation/spray/client/OutboundRequest.scala @@ -0,0 +1,25 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.newrelic.agent.security.instrumentation.spray.client + +import spray.http.{HttpHeaders, HttpRequest} + +/** + * Spray's HttpRequest is immutable so we have to create a copy with the new headers. + */ + +class OutboundRequest(request: HttpRequest) { + private var req: HttpRequest = request + + def setHeader(key: String, value: String): Unit = { + req = request.withHeaders(req.headers ++ List(HttpHeaders.RawHeader(key, value))) + } + def getRequest: HttpRequest = { + req + } +} \ No newline at end of file diff --git a/instrumentation-security/spray-client/src/main/scala/spray/client/SendReceive_Instrumentation.java b/instrumentation-security/spray-client/src/main/scala/spray/client/SendReceive_Instrumentation.java index 35e4d6a1a..96f6ac28f 100644 --- a/instrumentation-security/spray-client/src/main/scala/spray/client/SendReceive_Instrumentation.java +++ b/instrumentation-security/spray-client/src/main/scala/spray/client/SendReceive_Instrumentation.java @@ -1,12 +1,16 @@ package spray.client; +import com.newrelic.agent.security.instrumentation.spray.client.OutboundRequest; import com.newrelic.agent.security.instrumentation.spray.client.SprayUtils; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; +import com.newrelic.api.agent.security.utils.SSRFUtils; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -26,6 +30,7 @@ public final Future apply(HttpRequest request) { // Preprocess Phase if (isLockAcquired) { operation = preprocessSecurityHook(request); + request = addSecurityHeaders(request, operation); } Future returnCode; @@ -40,6 +45,34 @@ public final Future apply(HttpRequest request) { return returnCode; } + private HttpRequest addSecurityHeaders(HttpRequest request, AbstractOperation operation) { + OutboundRequest outboundRequest = new OutboundRequest(request); + if (operation!=null) { + SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + String iastHeader = NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getRaw(); + if (iastHeader != null && !iastHeader.trim().isEmpty()) { + outboundRequest.setHeader(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, iastHeader); + } + String csecParentId = securityMetaData.getCustomAttribute(GenericHelper.CSEC_PARENT_ID, String.class); + if(StringUtils.isNotBlank(csecParentId)){ + outboundRequest.setHeader(GenericHelper.CSEC_PARENT_ID, csecParentId); + } + + try { + NewRelicSecurity.getAgent().registerOperation(operation); + } finally { + if (operation.getApiID() != null && !operation.getApiID().trim().isEmpty() && + operation.getExecutionId() != null && !operation.getExecutionId().trim().isEmpty()) { + // Add Security distributed tracing header + outboundRequest.setHeader(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, + SSRFUtils.generateTracingHeaderValue(securityMetaData.getTracingHeaderValue(), + operation.getApiID(), operation.getExecutionId(), + NewRelicSecurity.getAgent().getAgentUUID())); + } + } + } + return outboundRequest.getRequest(); + } private void releaseLock() { try { GenericHelper.releaseLock(SprayUtils.getNrSecCustomAttribName()); From 389085eeef8a4460727b26632d12ba087b055e4f Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 26 Feb 2024 17:09:57 +0530 Subject: [PATCH 034/124] Unit tests for Spray client support Co-authored-by: Lovesh Baya --- .../spray/client/SprayCanClientTest.scala | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 instrumentation-security/spray-client/src/test/scala/com/newrelic/security/agent/spray/client/SprayCanClientTest.scala diff --git a/instrumentation-security/spray-client/src/test/scala/com/newrelic/security/agent/spray/client/SprayCanClientTest.scala b/instrumentation-security/spray-client/src/test/scala/com/newrelic/security/agent/spray/client/SprayCanClientTest.scala new file mode 100644 index 000000000..36a056279 --- /dev/null +++ b/instrumentation-security/spray-client/src/test/scala/com/newrelic/security/agent/spray/client/SprayCanClientTest.scala @@ -0,0 +1,118 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.newrelic.security.agent.spray.client + +import akka.actor._ +import com.newrelic.agent.security.instrumentation.spray.client.SprayUtils +import com.newrelic.agent.security.introspec.internal.HttpServerLocator +import com.newrelic.agent.security.introspec.{HttpTestServer, InstrumentationTestConfig, SecurityInstrumentationTestRunner, SecurityIntrospector} +import com.newrelic.api.agent.security.instrumentation.helpers.{GenericHelper, ServletHelper} +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType +import com.newrelic.api.agent.security.schema.operation.SSRFOperation +import com.newrelic.security.test.marker.{Java11IncompatibleTest, Java17IncompatibleTest} +import org.junit.experimental.categories.Category +import org.junit.runner.RunWith +import org.junit._ +import org.junit.runners.MethodSorters +import spray.client.pipelining +import spray.client.pipelining.Get + +import java.util.UUID +import scala.util.{Failure, Success} + +//// Not compatible with Java 11+ and Scala 2.13+ https://github.com/scala/bug/issues/12340 +@Category( Array(classOf[Java11IncompatibleTest], classOf[Java17IncompatibleTest] )) +@RunWith(classOf[SecurityInstrumentationTestRunner]) +@InstrumentationTestConfig(includePrefixes = Array("spray", "scala", "com.newrelic.agent.security.instrumentation")) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class SprayCanClientTest { + var server :HttpTestServer = HttpServerLocator.createAndStart() + implicit var system: ActorSystem = ActorSystem("spray-client") + val endpoint :String = server.getEndPoint.toString; + + @After + def after(): Unit = { + server.shutdown() + } + + @Test + def testSendReceive(): Unit = { + server.getHeaders.clear() + val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector + + requestApi() + + Assert.assertTrue("No operations detected", introspector.getOperations.size() > 0) + val operations: SSRFOperation = introspector.getOperations.get(0).asInstanceOf[SSRFOperation] + Assert.assertEquals("Invalid event category.", VulnerabilityCaseType.HTTP_REQUEST, operations.getCaseType) + Assert.assertEquals("Invalid method-name.", SprayUtils.METHOD_SEND_RECEIVE, operations.getMethodName) + Assert.assertEquals("Invalid ssrf arg.", endpoint, operations.getArg) + + val header: java.util.Map[String, String] = server.getHeaders + Assert.assertFalse(String.format("Found CSEC header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), header.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID)) + Assert.assertFalse(String.format("Found CSEC header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), header.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER)) + Assert.assertFalse(String.format("Found CSEC header: %s", GenericHelper.CSEC_PARENT_ID), header.containsKey(GenericHelper.CSEC_PARENT_ID)) + } + + @Test + def testSendReceiveWithHeader(): Unit = { + val headerValue = String.valueOf(UUID.randomUUID) + val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector + introspector.setK2FuzzRequestId(headerValue) + introspector.setK2TracingData(headerValue) + introspector.setK2ParentId(headerValue) + + requestApi() + + + Assert.assertTrue("No operations detected", introspector.getOperations.size() > 0) + val operations: SSRFOperation = introspector.getOperations.get(0).asInstanceOf[SSRFOperation] + Assert.assertEquals("Invalid event category.", VulnerabilityCaseType.HTTP_REQUEST, operations.getCaseType) + Assert.assertEquals("Invalid method-name.", SprayUtils.METHOD_SEND_RECEIVE, operations.getMethodName) + Assert.assertEquals("Invalid ssrf arg.", endpoint, operations.getArg) + + val header: java.util.Map[String, String] = server.getHeaders + Assert.assertTrue(String.format("Missing CSEC header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), header.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID)) + Assert.assertEquals( + String.format("Invalid CSEC header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), + headerValue, + header.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + ) + + Assert.assertTrue(String.format("Missing CSEC header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), header.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase)) + Assert.assertEquals( + String.format("Invalid CSEC header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), + String.format("%s;DUMMY_UUID/dummy-api-id/dummy-exec-id;", headerValue), + header.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase) + ) + Assert.assertTrue(String.format("Missing CSEC header: %s", GenericHelper.CSEC_PARENT_ID), header.containsKey(GenericHelper.CSEC_PARENT_ID)) + Assert.assertEquals( + String.format("Invalid CSEC header value for: %s", GenericHelper.CSEC_PARENT_ID), + headerValue, + header.get(GenericHelper.CSEC_PARENT_ID) + ) + } + + + def requestApi()(implicit system: ActorSystem): Unit = { + import system.dispatcher + val pipeline = pipelining.sendReceive + val responseFuture = pipeline {Get(endpoint)} + + responseFuture onComplete { + case Success(result) => + println("The API call was successful...: " + result) + system.shutdown() + + case Failure(error) => + println(error, "Couldn't get elevation") + system.shutdown() + } + system.awaitTermination + } +} From 9ae73e8c7c912be1093e1607659b96a1eec46ec5 Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Mon, 26 Feb 2024 18:33:50 +0530 Subject: [PATCH 035/124] [NR-222166] Unit tests & fixes for API endpoint support (#185) Unit tests & handler class fixes for API endpoint support * add filtering to jersey API endpoint, removed endpoints for model processors handler class * add handler details & enabled API endpoint support for servlet JSP Framework * Added unit tests for servlet API, JAX-RS Jersey, RestEasy, Spring-WebFlux, Spring-WebMVC endpoint support --- .../apache/struts2/StrutsHelper.java | 2 +- .../config/Configuration_Instrumentation.java | 2 +- .../apache/wicket6/WicketHelper.java | 2 +- .../apache/wicket7/WicketHelper.java | 2 +- .../apache/wicket8/WicketHelper.java | 2 +- .../grails13/GrailsHelper.java | 2 +- .../grails2/GrailsHelper.java | 2 +- .../grails3/GrailsHelper.java | 2 +- instrumentation-security/jersey/build.gradle | 4 + .../instrumentation}/jersey/JerseyHelper.java | 8 +- .../rs/api/app/CustomerLocatorResource.java | 17 ++++ .../javax/ws/rs/api/app/IdSubResource.java | 18 ++++ .../ws/rs/api/app/OrdersSubResource.java | 14 +++ .../javax/ws/rs/api/app/TestMapping.java | 25 +++++ .../javax/ws/rs/api/test/SubresourceTest.java | 66 +++++++++++++ .../resteasy-2.2/build.gradle | 1 + .../resteasy2/RestEasyHelper.java | 2 +- .../registry/RootSegment_Instrumentation.java | 2 +- .../app/CustomerLocatorResource.java | 24 +++++ .../resteasy2_2/app/TestMapping.java | 28 ++++++ .../resteasy2_2/test/APIEndpointTest.java | 75 +++++++++++++++ .../resteasy2_2/test/TestApplication.java | 92 +++++++++++++++++++ .../resteasy-3/build.gradle | 1 + .../resteasy3/RestEasyHelper.java | 2 +- .../RootClassNode_Instrumentation.java | 2 +- .../app/CustomerLocatorResource.java | 24 +++++ .../resteasy3/app/TestMapping.java | 28 ++++++ .../resteasy3/test/APIEndpointTest.java | 74 +++++++++++++++ .../resteasy3/test/TestApplication.java | 92 +++++++++++++++++++ .../resteasy4/RestEasyHelper.java | 2 +- .../RootClassNode_Instrumentation.java | 2 +- .../servlet24/HttpServletHelper.java | 2 +- ...tContainerInitializer_Instrumentation.java | 4 +- .../servlet24/HttpServletServer.java | 20 +++- .../ServletContainerInitializerTest.java | 34 +++++++ .../servlet5/HttpServletHelper.java | 2 +- ...tContainerInitializer_Instrumentation.java | 4 +- .../servlet5/HttpServletServer.java | 13 +++ .../ServletContainerInitializerTest.java | 34 +++++++ .../servlet6/HttpServletHelper.java | 2 +- ...tContainerInitializer_Instrumentation.java | 4 +- .../servlet6/HttpServletServer.java | 13 +++ .../ServletContainerInitializerTest.java | 34 +++++++ .../spring-webflux/build.gradle | 3 + .../spring/webmvc/APIEndpointTest.java | 61 ++++++++++++ .../spring/webmvc/TestMappings.java | 48 ++++++++++ .../spring-webmvc-3.1.0/build.gradle | 2 + .../spring/webmvc/APIEndpointTest.java | 63 +++++++++++++ .../spring/webmvc/TestMappings.java | 34 +++++++ .../spring-webmvc-5.3.0/build.gradle | 2 + .../spring/webmvc/APIEndpointTest.java | 63 +++++++++++++ .../spring/webmvc/TestMappings.java | 49 ++++++++++ 52 files changed, 1084 insertions(+), 26 deletions(-) rename instrumentation-security/apache-struts2/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/apache/struts2/StrutsHelper.java (95%) rename instrumentation-security/apache-wicket-6.4/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/apache/wicket6/WicketHelper.java (92%) rename instrumentation-security/apache-wicket-7.0/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/apache/wicket7/WicketHelper.java (92%) rename instrumentation-security/apache-wicket-8.0/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/apache/wicket8/WicketHelper.java (92%) rename instrumentation-security/grails-1.3/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/grails13/GrailsHelper.java (90%) rename instrumentation-security/grails-2.0/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/grails2/GrailsHelper.java (90%) rename instrumentation-security/grails-3.0/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/grails3/GrailsHelper.java (94%) rename instrumentation-security/jersey/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/jersey/JerseyHelper.java (86%) create mode 100644 instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/CustomerLocatorResource.java create mode 100644 instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/IdSubResource.java create mode 100644 instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/OrdersSubResource.java create mode 100644 instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/TestMapping.java create mode 100644 instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java rename instrumentation-security/resteasy-2.2/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/resteasy2/RestEasyHelper.java (96%) create mode 100644 instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/app/CustomerLocatorResource.java create mode 100644 instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/app/TestMapping.java create mode 100644 instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/test/APIEndpointTest.java create mode 100644 instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/test/TestApplication.java rename instrumentation-security/resteasy-3/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/resteasy3/RestEasyHelper.java (96%) create mode 100644 instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/app/CustomerLocatorResource.java create mode 100644 instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/app/TestMapping.java create mode 100644 instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/test/APIEndpointTest.java create mode 100644 instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/test/TestApplication.java rename instrumentation-security/resteasy-4/src/main/java/com/{nr/instrumentation/security => newrelic/agent/security/instrumentation}/resteasy4/RestEasyHelper.java (96%) create mode 100644 instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletContainerInitializerTest.java create mode 100644 instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java create mode 100644 instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java create mode 100644 instrumentation-security/spring-webflux/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java create mode 100644 instrumentation-security/spring-webflux/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java create mode 100644 instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java create mode 100644 instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java create mode 100644 instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java create mode 100644 instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java diff --git a/instrumentation-security/apache-struts2/src/main/java/com/nr/instrumentation/security/apache/struts2/StrutsHelper.java b/instrumentation-security/apache-struts2/src/main/java/com/newrelic/agent/security/instrumentation/apache/struts2/StrutsHelper.java similarity index 95% rename from instrumentation-security/apache-struts2/src/main/java/com/nr/instrumentation/security/apache/struts2/StrutsHelper.java rename to instrumentation-security/apache-struts2/src/main/java/com/newrelic/agent/security/instrumentation/apache/struts2/StrutsHelper.java index a36fee7cd..bca7db4a9 100644 --- a/instrumentation-security/apache-struts2/src/main/java/com/nr/instrumentation/security/apache/struts2/StrutsHelper.java +++ b/instrumentation-security/apache-struts2/src/main/java/com/newrelic/agent/security/instrumentation/apache/struts2/StrutsHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.apache.struts2; +package com.newrelic.agent.security.instrumentation.apache.struts2; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.instrumentation.helpers.*; diff --git a/instrumentation-security/apache-struts2/src/main/java/com/opensymphony/xwork2/config/Configuration_Instrumentation.java b/instrumentation-security/apache-struts2/src/main/java/com/opensymphony/xwork2/config/Configuration_Instrumentation.java index 136f3ea81..62d09202e 100644 --- a/instrumentation-security/apache-struts2/src/main/java/com/opensymphony/xwork2/config/Configuration_Instrumentation.java +++ b/instrumentation-security/apache-struts2/src/main/java/com/opensymphony/xwork2/config/Configuration_Instrumentation.java @@ -3,7 +3,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.nr.instrumentation.security.apache.struts2.StrutsHelper; +import com.newrelic.agent.security.instrumentation.apache.struts2.StrutsHelper; import java.util.List; @Weave(type = MatchType.Interface, originalName = "com.opensymphony.xwork2.config.Configuration") diff --git a/instrumentation-security/apache-wicket-6.4/src/main/java/com/nr/instrumentation/security/apache/wicket6/WicketHelper.java b/instrumentation-security/apache-wicket-6.4/src/main/java/com/newrelic/agent/security/instrumentation/apache/wicket6/WicketHelper.java similarity index 92% rename from instrumentation-security/apache-wicket-6.4/src/main/java/com/nr/instrumentation/security/apache/wicket6/WicketHelper.java rename to instrumentation-security/apache-wicket-6.4/src/main/java/com/newrelic/agent/security/instrumentation/apache/wicket6/WicketHelper.java index 5439f2565..8a79ce975 100644 --- a/instrumentation-security/apache-wicket-6.4/src/main/java/com/nr/instrumentation/security/apache/wicket6/WicketHelper.java +++ b/instrumentation-security/apache-wicket-6.4/src/main/java/com/newrelic/agent/security/instrumentation/apache/wicket6/WicketHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.apache.wicket6; +package com.newrelic.agent.security.instrumentation.apache.wicket6; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; diff --git a/instrumentation-security/apache-wicket-7.0/src/main/java/com/nr/instrumentation/security/apache/wicket7/WicketHelper.java b/instrumentation-security/apache-wicket-7.0/src/main/java/com/newrelic/agent/security/instrumentation/apache/wicket7/WicketHelper.java similarity index 92% rename from instrumentation-security/apache-wicket-7.0/src/main/java/com/nr/instrumentation/security/apache/wicket7/WicketHelper.java rename to instrumentation-security/apache-wicket-7.0/src/main/java/com/newrelic/agent/security/instrumentation/apache/wicket7/WicketHelper.java index 651761e99..954fb676b 100644 --- a/instrumentation-security/apache-wicket-7.0/src/main/java/com/nr/instrumentation/security/apache/wicket7/WicketHelper.java +++ b/instrumentation-security/apache-wicket-7.0/src/main/java/com/newrelic/agent/security/instrumentation/apache/wicket7/WicketHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.apache.wicket7; +package com.newrelic.agent.security.instrumentation.apache.wicket7; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; diff --git a/instrumentation-security/apache-wicket-8.0/src/main/java/com/nr/instrumentation/security/apache/wicket8/WicketHelper.java b/instrumentation-security/apache-wicket-8.0/src/main/java/com/newrelic/agent/security/instrumentation/apache/wicket8/WicketHelper.java similarity index 92% rename from instrumentation-security/apache-wicket-8.0/src/main/java/com/nr/instrumentation/security/apache/wicket8/WicketHelper.java rename to instrumentation-security/apache-wicket-8.0/src/main/java/com/newrelic/agent/security/instrumentation/apache/wicket8/WicketHelper.java index 376109337..9510e5958 100644 --- a/instrumentation-security/apache-wicket-8.0/src/main/java/com/nr/instrumentation/security/apache/wicket8/WicketHelper.java +++ b/instrumentation-security/apache-wicket-8.0/src/main/java/com/newrelic/agent/security/instrumentation/apache/wicket8/WicketHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.apache.wicket8; +package com.newrelic.agent.security.instrumentation.apache.wicket8; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; diff --git a/instrumentation-security/grails-1.3/src/main/java/com/nr/instrumentation/security/grails13/GrailsHelper.java b/instrumentation-security/grails-1.3/src/main/java/com/newrelic/agent/security/instrumentation/grails13/GrailsHelper.java similarity index 90% rename from instrumentation-security/grails-1.3/src/main/java/com/nr/instrumentation/security/grails13/GrailsHelper.java rename to instrumentation-security/grails-1.3/src/main/java/com/newrelic/agent/security/instrumentation/grails13/GrailsHelper.java index ad89554f9..f7883b7da 100644 --- a/instrumentation-security/grails-1.3/src/main/java/com/nr/instrumentation/security/grails13/GrailsHelper.java +++ b/instrumentation-security/grails-1.3/src/main/java/com/newrelic/agent/security/instrumentation/grails13/GrailsHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.grails13; +package com.newrelic.agent.security.instrumentation.grails13; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; diff --git a/instrumentation-security/grails-2.0/src/main/java/com/nr/instrumentation/security/grails2/GrailsHelper.java b/instrumentation-security/grails-2.0/src/main/java/com/newrelic/agent/security/instrumentation/grails2/GrailsHelper.java similarity index 90% rename from instrumentation-security/grails-2.0/src/main/java/com/nr/instrumentation/security/grails2/GrailsHelper.java rename to instrumentation-security/grails-2.0/src/main/java/com/newrelic/agent/security/instrumentation/grails2/GrailsHelper.java index f0c56410c..93d1856c5 100644 --- a/instrumentation-security/grails-2.0/src/main/java/com/nr/instrumentation/security/grails2/GrailsHelper.java +++ b/instrumentation-security/grails-2.0/src/main/java/com/newrelic/agent/security/instrumentation/grails2/GrailsHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.grails2; +package com.newrelic.agent.security.instrumentation.grails2; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; diff --git a/instrumentation-security/grails-3.0/src/main/java/com/nr/instrumentation/security/grails3/GrailsHelper.java b/instrumentation-security/grails-3.0/src/main/java/com/newrelic/agent/security/instrumentation/grails3/GrailsHelper.java similarity index 94% rename from instrumentation-security/grails-3.0/src/main/java/com/nr/instrumentation/security/grails3/GrailsHelper.java rename to instrumentation-security/grails-3.0/src/main/java/com/newrelic/agent/security/instrumentation/grails3/GrailsHelper.java index dbbae1fdd..64ab175ed 100644 --- a/instrumentation-security/grails-3.0/src/main/java/com/nr/instrumentation/security/grails3/GrailsHelper.java +++ b/instrumentation-security/grails-3.0/src/main/java/com/newrelic/agent/security/instrumentation/grails3/GrailsHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.grails3; +package com.newrelic.agent.security.instrumentation.grails3; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; diff --git a/instrumentation-security/jersey/build.gradle b/instrumentation-security/jersey/build.gradle index e39469d3c..2a7535835 100644 --- a/instrumentation-security/jersey/build.gradle +++ b/instrumentation-security/jersey/build.gradle @@ -3,6 +3,10 @@ dependencies { implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation('org.glassfish.jersey.core:jersey-server:2.28') + testImplementation("org.glassfish.jersey.containers:jersey-container-servlet:2.28") + testImplementation("org.glassfish.jersey.test-framework:jersey-test-framework-core:2.28") + testImplementation("org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-grizzly2:2.28") + testImplementation("org.glassfish.jersey.inject:jersey-hk2:2.28") } diff --git a/instrumentation-security/jersey/src/main/java/com/nr/instrumentation/security/jersey/JerseyHelper.java b/instrumentation-security/jersey/src/main/java/com/newrelic/agent/security/instrumentation/jersey/JerseyHelper.java similarity index 86% rename from instrumentation-security/jersey/src/main/java/com/nr/instrumentation/security/jersey/JerseyHelper.java rename to instrumentation-security/jersey/src/main/java/com/newrelic/agent/security/instrumentation/jersey/JerseyHelper.java index 5855f7d64..8b6b88053 100644 --- a/instrumentation-security/jersey/src/main/java/com/nr/instrumentation/security/jersey/JerseyHelper.java +++ b/instrumentation-security/jersey/src/main/java/com/newrelic/agent/security/instrumentation/jersey/JerseyHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.jersey; +package com.newrelic.agent.security.instrumentation.jersey; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.instrumentation.helpers.*; @@ -14,6 +14,8 @@ public class JerseyHelper { private static final String EMPTY = ""; private static final String WILDCARD = "*"; private static final String SEPARATOR = "/"; + public static final String ORG_GLASSFISH_JERSEY_SERVER_WADL = "org.glassfish.jersey.server.wadl"; + public static void gatherUrlMappings(ResourceModel resourceModel) { try { List resources = resourceModel.getResources(); @@ -56,7 +58,9 @@ private static void extractMappingsFromResources(List resources, Strin private static void addURLMappings(String url, String httpMethod, Set> handlerClasses) { for (Class handlerClass : handlerClasses) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(httpMethod, url, handlerClass.getName())); + if (!handlerClass.getName().startsWith(ORG_GLASSFISH_JERSEY_SERVER_WADL)){ + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(httpMethod, url, handlerClass.getName())); + } } } } diff --git a/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/CustomerLocatorResource.java b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/CustomerLocatorResource.java new file mode 100644 index 000000000..9da61e921 --- /dev/null +++ b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/CustomerLocatorResource.java @@ -0,0 +1,17 @@ +package com.nr.agent.security.instrumentation.javax.ws.rs.api.app; + +import javax.ws.rs.Path; + +@Path("/customers") +public class CustomerLocatorResource { + + protected OrdersSubResource ordersSubResource = new OrdersSubResource(); + + @Path("orders") + public Object getOrders() { + return ordersSubResource; + } + + +} + diff --git a/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/IdSubResource.java b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/IdSubResource.java new file mode 100644 index 000000000..f65be73fa --- /dev/null +++ b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/IdSubResource.java @@ -0,0 +1,18 @@ +package com.nr.agent.security.instrumentation.javax.ws.rs.api.app; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; + +public class IdSubResource { + + + @GET + @Path("{id}") + @Produces("application/json") + public String getById(@PathParam("id") int id) { + return "one"; + } + +} diff --git a/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/OrdersSubResource.java b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/OrdersSubResource.java new file mode 100644 index 000000000..421b221f9 --- /dev/null +++ b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/OrdersSubResource.java @@ -0,0 +1,14 @@ +package com.nr.agent.security.instrumentation.javax.ws.rs.api.app; + +import javax.ws.rs.Path; + +public class OrdersSubResource { + + protected IdSubResource idType = new IdSubResource(); + + @Path("getStuff") + public Object getById() { + return idType; + } + +} diff --git a/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/TestMapping.java b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/TestMapping.java new file mode 100644 index 000000000..3f070a56a --- /dev/null +++ b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/app/TestMapping.java @@ -0,0 +1,25 @@ +package com.nr.agent.security.instrumentation.javax.ws.rs.api.app; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; + +@Path("users") + public class TestMapping { + @PUT + @Consumes("application/json") + public String putIt() { + return "Put it!"; + } + + + @Path("count") + @GET + @Consumes("application/json") + public String pathIt() { + return "path it!"; + } + } + + diff --git a/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java new file mode 100644 index 000000000..384ef769d --- /dev/null +++ b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java @@ -0,0 +1,66 @@ +package com.nr.agent.security.instrumentation.javax.ws.rs.api.test; + +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.CustomerLocatorResource; +import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.IdSubResource; +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.agent.security.introspec.SecurityIntrospector; +import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.OrdersSubResource; +import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.TestMapping; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Response; +import java.util.Iterator; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = { "com.nr.instrumentation.security.jersey", "org.glassfish.jersey.server.internal" }) +public class SubresourceTest extends JerseyTest { + @BeforeClass + public static void bringUp() { + System.setProperty("jersey.config.test.container.port", "0"); + } + + @Test + public void testAPIEndpoints() { + target("/customers/orders/getStuff/1").request().get(); + + Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); + + Assert.assertTrue(mappings.hasNext()); + assertMapping("/customers/orders/*", "*", CustomerLocatorResource.class.getName(), mappings.next()); + + Assert.assertTrue(mappings.hasNext()); + assertMapping("/users/count", "GET", TestMapping.class.getName(), mappings.next()); + + Assert.assertTrue(mappings.hasNext()); + assertMapping("/users", "PUT", TestMapping.class.getName(), mappings.next()); + + Assert.assertTrue(mappings.hasNext()); + assertMapping("/users", "OPTIONS", TestMapping.class.getName(), mappings.next()); + + Assert.assertTrue(mappings.hasNext()); + assertMapping("/users/count", "OPTIONS", TestMapping.class.getName(), mappings.next()); + } + + private void assertMapping(String path, String method, String handler, ApplicationURLMapping actualMapping){ + Assert.assertEquals(path, actualMapping.getPath()); + Assert.assertEquals(method, actualMapping.getMethod()); + Assert.assertEquals(handler, actualMapping.getHandler()); + } + + @Override + protected Application configure() { + return new ResourceConfig(CustomerLocatorResource.class, IdSubResource.class, OrdersSubResource.class, TestMapping.class); + } +} diff --git a/instrumentation-security/resteasy-2.2/build.gradle b/instrumentation-security/resteasy-2.2/build.gradle index 1e74c9fb7..b224f25f4 100644 --- a/instrumentation-security/resteasy-2.2/build.gradle +++ b/instrumentation-security/resteasy-2.2/build.gradle @@ -3,6 +3,7 @@ dependencies { implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation("org.jboss.resteasy:resteasy-jaxrs:2.3.3.Final") + testImplementation('org.apache.tomcat.embed:tomcat-embed-core:9.0.62') } jar { diff --git a/instrumentation-security/resteasy-2.2/src/main/java/com/nr/instrumentation/security/resteasy2/RestEasyHelper.java b/instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java similarity index 96% rename from instrumentation-security/resteasy-2.2/src/main/java/com/nr/instrumentation/security/resteasy2/RestEasyHelper.java rename to instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java index 958816739..38bca27e3 100644 --- a/instrumentation-security/resteasy-2.2/src/main/java/com/nr/instrumentation/security/resteasy2/RestEasyHelper.java +++ b/instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.resteasy2; +package com.newrelic.agent.security.instrumentation.resteasy2; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; diff --git a/instrumentation-security/resteasy-2.2/src/main/java/org/jboss/resteasy/core/registry/RootSegment_Instrumentation.java b/instrumentation-security/resteasy-2.2/src/main/java/org/jboss/resteasy/core/registry/RootSegment_Instrumentation.java index 08e784376..bbd0be248 100644 --- a/instrumentation-security/resteasy-2.2/src/main/java/org/jboss/resteasy/core/registry/RootSegment_Instrumentation.java +++ b/instrumentation-security/resteasy-2.2/src/main/java/org/jboss/resteasy/core/registry/RootSegment_Instrumentation.java @@ -3,7 +3,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.nr.instrumentation.security.resteasy2.RestEasyHelper; +import com.newrelic.agent.security.instrumentation.resteasy2.RestEasyHelper; import org.jboss.resteasy.core.ResourceInvoker; @Weave(type = MatchType.ExactClass, originalName = "org.jboss.resteasy.core.registry.RootSegment") diff --git a/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/app/CustomerLocatorResource.java b/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/app/CustomerLocatorResource.java new file mode 100644 index 000000000..40cedd202 --- /dev/null +++ b/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/app/CustomerLocatorResource.java @@ -0,0 +1,24 @@ +package com.nr.instrumentation.resteasy2_2.app; + +import javax.ws.rs.Path; + +@Path("/customers") +public class CustomerLocatorResource { + + protected OrdersSubResource ordersSubResource = new OrdersSubResource(); + + @Path("orders") + public Object getOrders() { + return ordersSubResource; + } + +} + +class OrdersSubResource { + protected TestMapping idType = new TestMapping(); + + @Path("getStuff") + public Object getById() { + return idType; + } +} \ No newline at end of file diff --git a/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/app/TestMapping.java b/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/app/TestMapping.java new file mode 100644 index 000000000..1f77bf530 --- /dev/null +++ b/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/app/TestMapping.java @@ -0,0 +1,28 @@ +package com.nr.instrumentation.resteasy2_2.app; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; + +@Path("users") +public class TestMapping { + @GET + public String getIt() { + return "Get it!"; + } + + @PUT + public String putIt() { + return "Put it!"; + } + + @Path("count") + @GET + @Consumes("application/json") + public String pathIt() { + return "path it!"; + } +} + + diff --git a/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/test/APIEndpointTest.java b/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/test/APIEndpointTest.java new file mode 100644 index 000000000..905abac5b --- /dev/null +++ b/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/test/APIEndpointTest.java @@ -0,0 +1,75 @@ +package com.nr.instrumentation.resteasy2_2.test; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.nr.instrumentation.resteasy2_2.app.CustomerLocatorResource; +import com.nr.instrumentation.resteasy2_2.app.TestMapping; +import org.apache.catalina.LifecycleException; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.lang.instrument.UnmodifiableClassException; +import java.net.HttpURLConnection; +import java.util.Iterator; +import java.util.Set; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = {"com.newrelic.agent.security.instrumentation.resteasy2", "org.jboss.resteasy.core.registry"}) +public class APIEndpointTest { + + private final String handler = TestMapping.class.getName(); + private final String path = "/users"; + + @BeforeClass + public static void startServer() throws LifecycleException, UnmodifiableClassException, ClassNotFoundException { + SecurityInstrumentationTestRunner.instrumentation.retransformClasses(Class.forName("org.jboss.resteasy.logging.Logger")); + TestApplication.startServer(); + } + + @AfterClass + public static void stopServer() { + TestApplication.stopServer(); + } + + @Test + public void testURLMappings() throws IOException { + service(); + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + + Assert.assertEquals(4, mappings.size()); + + Iterator mapping = mappings.iterator(); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("GET", path, handler, mapping.next()); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("GET", path +"/count", handler, mapping.next()); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("PUT", path, handler, mapping.next()); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("*", "/customers/orders/*", CustomerLocatorResource.class.getName(), mapping.next()); + } + + private void assertMapping(String method, String path, String handler, ApplicationURLMapping actualMapping) { + Assert.assertEquals(method, actualMapping.getMethod()); + Assert.assertEquals(path, actualMapping.getPath()); + Assert.assertEquals(handler, actualMapping.getHandler()); + } + + @Trace(dispatcher = true) + private void service() throws IOException { + HttpURLConnection conn = (HttpURLConnection) TestApplication.getEndPoint("users").openConnection(); + conn.connect(); + conn.getResponseCode(); + } +} diff --git a/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/test/TestApplication.java b/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/test/TestApplication.java new file mode 100644 index 000000000..9e1fe44ff --- /dev/null +++ b/instrumentation-security/resteasy-2.2/src/test/java/com/nr/instrumentation/resteasy2_2/test/TestApplication.java @@ -0,0 +1,92 @@ +package com.nr.instrumentation.resteasy2_2.test; + +import com.nr.instrumentation.resteasy2_2.app.CustomerLocatorResource; +import com.nr.instrumentation.resteasy2_2.app.TestMapping; +import org.apache.catalina.Context; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.LifecycleState; +import org.apache.catalina.connector.Connector; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory; +import org.apache.tomcat.util.http.fileupload.FileUtils; +import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher; +import org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap; + +import javax.ws.rs.core.Application; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.ServerSocket; +import java.net.URL; +import java.util.HashSet; +import java.util.Set; + +public class TestApplication extends Application { + + private final Set classes = new HashSet<>(); + private static Tomcat tomcat; + private static int port; + private static final File tmp = new File("./tmp"); + + public TestApplication() { + classes.add(new CustomerLocatorResource()); + classes.add(new TestMapping()); + } + + @Override + public Set getSingletons() { + return classes; + } + + public static void startServer() throws LifecycleException { + TomcatURLStreamHandlerFactory.disable(); + getRandomPort(); + + tomcat = new Tomcat(); + tomcat.setPort(port); + + String workingDir = tmp.getAbsolutePath(); + + tomcat.setBaseDir(workingDir); + tomcat.getHost().setAppBase(workingDir); + + Context context = tomcat.addContext("/api", workingDir); + context.addApplicationListener(ResteasyBootstrap.class.getName()); + + Tomcat.addServlet(context, "resteasy-servlet", new HttpServletDispatcher()); + context.addParameter("resteasy.scan", "true"); + context.addParameter(Application.class.getName(), TestApplication.class.getName()); + context.addServletMappingDecoded("/*", "resteasy-servlet"); + + final Connector connector = new Connector(); + connector.setPort(port); + + tomcat.getService().addConnector(connector); + tomcat.start(); + } + + public static void stopServer() { + if (tomcat.getServer() != null && tomcat.getServer().getState() != LifecycleState.DESTROYED) { + try { + if (tomcat.getServer().getState() != LifecycleState.STOPPED) { + tomcat.stop(); + } + tomcat.destroy(); + FileUtils.forceDelete(tmp); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static URL getEndPoint(String path) throws MalformedURLException { + return new URL("http://localhost:" + port + "/api/" + path); + } + private static void getRandomPort() { + try (ServerSocket socket = new ServerSocket(0)){ + port = socket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Unable to allocate ephemeral port "+ port); + } + } +} diff --git a/instrumentation-security/resteasy-3/build.gradle b/instrumentation-security/resteasy-3/build.gradle index 7f7c8100f..b0571720a 100644 --- a/instrumentation-security/resteasy-3/build.gradle +++ b/instrumentation-security/resteasy-3/build.gradle @@ -3,6 +3,7 @@ dependencies { implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation("org.jboss.resteasy:resteasy-jaxrs:3.0.0.Final") + testImplementation('org.apache.tomcat.embed:tomcat-embed-core:9.0.70') } jar { diff --git a/instrumentation-security/resteasy-3/src/main/java/com/nr/instrumentation/security/resteasy3/RestEasyHelper.java b/instrumentation-security/resteasy-3/src/main/java/com/newrelic/agent/security/instrumentation/resteasy3/RestEasyHelper.java similarity index 96% rename from instrumentation-security/resteasy-3/src/main/java/com/nr/instrumentation/security/resteasy3/RestEasyHelper.java rename to instrumentation-security/resteasy-3/src/main/java/com/newrelic/agent/security/instrumentation/resteasy3/RestEasyHelper.java index b79372d3d..f309a2e86 100644 --- a/instrumentation-security/resteasy-3/src/main/java/com/nr/instrumentation/security/resteasy3/RestEasyHelper.java +++ b/instrumentation-security/resteasy-3/src/main/java/com/newrelic/agent/security/instrumentation/resteasy3/RestEasyHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.resteasy3; +package com.newrelic.agent.security.instrumentation.resteasy3; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; diff --git a/instrumentation-security/resteasy-3/src/main/java/org/jboss/resteasy/core/registry/RootClassNode_Instrumentation.java b/instrumentation-security/resteasy-3/src/main/java/org/jboss/resteasy/core/registry/RootClassNode_Instrumentation.java index 82261a01f..58d8c90e6 100644 --- a/instrumentation-security/resteasy-3/src/main/java/org/jboss/resteasy/core/registry/RootClassNode_Instrumentation.java +++ b/instrumentation-security/resteasy-3/src/main/java/org/jboss/resteasy/core/registry/RootClassNode_Instrumentation.java @@ -3,7 +3,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.nr.instrumentation.security.resteasy3.RestEasyHelper; +import com.newrelic.agent.security.instrumentation.resteasy3.RestEasyHelper; import org.jboss.resteasy.core.ResourceInvoker; @Weave(type = MatchType.ExactClass, originalName = "org.jboss.resteasy.core.registry.RootClassNode") diff --git a/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/app/CustomerLocatorResource.java b/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/app/CustomerLocatorResource.java new file mode 100644 index 000000000..bd29209df --- /dev/null +++ b/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/app/CustomerLocatorResource.java @@ -0,0 +1,24 @@ +package com.nr.instrumentation.resteasy3.app; + +import javax.ws.rs.Path; + +@Path("/customers") +public class CustomerLocatorResource { + + protected OrdersSubResource ordersSubResource = new OrdersSubResource(); + + @Path("orders") + public Object getOrders() { + return ordersSubResource; + } + +} + +class OrdersSubResource { + protected TestMapping idType = new TestMapping(); + + @Path("getStuff") + public Object getById() { + return idType; + } +} \ No newline at end of file diff --git a/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/app/TestMapping.java b/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/app/TestMapping.java new file mode 100644 index 000000000..88a116edd --- /dev/null +++ b/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/app/TestMapping.java @@ -0,0 +1,28 @@ +package com.nr.instrumentation.resteasy3.app; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; + +@Path("users") +public class TestMapping { + @GET + public String getIt() { + return "Get it!"; + } + + @PUT + public String putIt() { + return "Put it!"; + } + + @Path("count") + @GET + @Consumes("application/json") + public String pathIt() { + return "path it!"; + } +} + + diff --git a/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/test/APIEndpointTest.java b/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/test/APIEndpointTest.java new file mode 100644 index 000000000..c4b70025c --- /dev/null +++ b/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/test/APIEndpointTest.java @@ -0,0 +1,74 @@ +package com.nr.instrumentation.resteasy3.test; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.nr.instrumentation.resteasy3.app.CustomerLocatorResource; +import com.nr.instrumentation.resteasy3.app.TestMapping; +import org.apache.catalina.LifecycleException; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.lang.instrument.UnmodifiableClassException; +import java.net.HttpURLConnection; +import java.util.Iterator; +import java.util.Set; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = {"com.newrelic.agent.security.instrumentation.resteasy3", "org.jboss.resteasy.core.registry"}) +public class APIEndpointTest { + private final String handler = TestMapping.class.getName(); + private final String path = "/users"; + + @BeforeClass + public static void startServer() throws LifecycleException, UnmodifiableClassException, ClassNotFoundException { + SecurityInstrumentationTestRunner.instrumentation.retransformClasses(Class.forName("org.jboss.resteasy.logging.Logger")); + TestApplication.startServer(); + } + + @AfterClass + public static void stopServer() { + TestApplication.stopServer(); + } + + @Test + public void testURLMappings() throws IOException { + service(); + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + + Assert.assertEquals(4, mappings.size()); + + Iterator mapping = mappings.iterator(); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("*", "/customers/orders/*", CustomerLocatorResource.class.getName(), mapping.next()); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("GET", path, handler, mapping.next()); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("GET", path +"/count", handler, mapping.next()); + + Assert.assertTrue(mapping.hasNext()); + assertMapping("PUT", path, handler, mapping.next()); + } + + private void assertMapping(String method, String path, String handler, ApplicationURLMapping actualMapping) { + Assert.assertEquals(method, actualMapping.getMethod()); + Assert.assertEquals(path, actualMapping.getPath()); + Assert.assertEquals(handler, actualMapping.getHandler()); + } + + @Trace(dispatcher = true) + private void service() throws IOException { + HttpURLConnection conn = (HttpURLConnection)TestApplication.getEndPoint("customers/getStuff/users").openConnection(); + conn.connect(); + conn.getResponseCode(); + } +} diff --git a/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/test/TestApplication.java b/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/test/TestApplication.java new file mode 100644 index 000000000..32b9c5a4f --- /dev/null +++ b/instrumentation-security/resteasy-3/src/test/java/com/nr/instrumentation/resteasy3/test/TestApplication.java @@ -0,0 +1,92 @@ +package com.nr.instrumentation.resteasy3.test; + +import com.nr.instrumentation.resteasy3.app.CustomerLocatorResource; +import com.nr.instrumentation.resteasy3.app.TestMapping; +import org.apache.catalina.Context; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.LifecycleState; +import org.apache.catalina.connector.Connector; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory; +import org.apache.tomcat.util.http.fileupload.FileUtils; +import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher; +import org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap; + +import javax.ws.rs.core.Application; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.ServerSocket; +import java.net.URL; +import java.util.HashSet; +import java.util.Set; + +public class TestApplication extends Application { + + private final Set classes = new HashSet<>(); + private static Tomcat tomcat; + private static int port; + private static final File tmp = new File("./tmp"); + + public TestApplication() { + classes.add(new CustomerLocatorResource()); + classes.add(new TestMapping()); + } + + @Override + public Set getSingletons() { + return classes; + } + + public static void startServer() throws LifecycleException { + TomcatURLStreamHandlerFactory.disable(); + getRandomPort(); + + tomcat = new Tomcat(); + tomcat.setPort(port); + + String workingDir = tmp.getAbsolutePath(); + + tomcat.setBaseDir(workingDir); + tomcat.getHost().setAppBase(workingDir); + + Context context = tomcat.addContext("/api", workingDir); + context.addApplicationListener(ResteasyBootstrap.class.getName()); + + Tomcat.addServlet(context, "resteasy-servlet", new HttpServletDispatcher()); + context.addParameter("resteasy.scan", "true"); + context.addParameter(Application.class.getName(), TestApplication.class.getName()); + context.addServletMappingDecoded("/*", "resteasy-servlet"); + + final Connector connector = new Connector(); + connector.setPort(port); + + tomcat.getService().addConnector(connector); + tomcat.start(); + } + + public static void stopServer() { + if (tomcat.getServer() != null && tomcat.getServer().getState() != LifecycleState.DESTROYED) { + try { + if (tomcat.getServer().getState() != LifecycleState.STOPPED) { + tomcat.stop(); + } + tomcat.destroy(); + FileUtils.forceDelete(tmp); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static URL getEndPoint(String path) throws MalformedURLException { + return new URL("http://localhost:" + port + "/api/" + path); + } + private static void getRandomPort() { + try (ServerSocket socket = new ServerSocket(0)){ + port = socket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Unable to allocate ephemeral port "+ port); + } + } +} diff --git a/instrumentation-security/resteasy-4/src/main/java/com/nr/instrumentation/security/resteasy4/RestEasyHelper.java b/instrumentation-security/resteasy-4/src/main/java/com/newrelic/agent/security/instrumentation/resteasy4/RestEasyHelper.java similarity index 96% rename from instrumentation-security/resteasy-4/src/main/java/com/nr/instrumentation/security/resteasy4/RestEasyHelper.java rename to instrumentation-security/resteasy-4/src/main/java/com/newrelic/agent/security/instrumentation/resteasy4/RestEasyHelper.java index c7230d733..795b5633a 100644 --- a/instrumentation-security/resteasy-4/src/main/java/com/nr/instrumentation/security/resteasy4/RestEasyHelper.java +++ b/instrumentation-security/resteasy-4/src/main/java/com/newrelic/agent/security/instrumentation/resteasy4/RestEasyHelper.java @@ -1,4 +1,4 @@ -package com.nr.instrumentation.security.resteasy4; +package com.newrelic.agent.security.instrumentation.resteasy4; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; diff --git a/instrumentation-security/resteasy-4/src/main/java/org/jboss/resteasy/core/registry/RootClassNode_Instrumentation.java b/instrumentation-security/resteasy-4/src/main/java/org/jboss/resteasy/core/registry/RootClassNode_Instrumentation.java index 2a98b0b9f..e4ffd7440 100644 --- a/instrumentation-security/resteasy-4/src/main/java/org/jboss/resteasy/core/registry/RootClassNode_Instrumentation.java +++ b/instrumentation-security/resteasy-4/src/main/java/org/jboss/resteasy/core/registry/RootClassNode_Instrumentation.java @@ -3,7 +3,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.nr.instrumentation.security.resteasy4.RestEasyHelper; +import com.newrelic.agent.security.instrumentation.resteasy4.RestEasyHelper; import org.jboss.resteasy.spi.ResourceInvoker; @Weave(type = MatchType.ExactClass, originalName = "org.jboss.resteasy.core.registry.RootClassNode") diff --git a/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java b/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java index b6ac6bbf7..754ff8f58 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java +++ b/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java @@ -126,7 +126,7 @@ public static void gatherURLMappings(ServletContext servletContext) { for (ServletRegistration servletRegistration : servletRegistrations.values()) { for (String s : servletRegistration.getMappings()) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, s)); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, s, servletRegistration.getClassName())); } } } catch (Exception e){ diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java index 90cd830ac..9a46ec883 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java @@ -1,11 +1,13 @@ package javax.servlet; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import com.newrelic.agent.security.instrumentation.servlet24.HttpServletHelper; import java.util.Set; -//@Weave(type = MatchType.Interface, originalName = "javax.servlet.ServletContainerInitializer") +@Weave(type = MatchType.Interface, originalName = "javax.servlet.ServletContainerInitializer") public class ServletContainerInitializer_Instrumentation { public void onStartup(Set> c, ServletContext ctx) throws ServletException { try { diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletServer.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletServer.java index c9ea9821f..e81e85dd9 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletServer.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletServer.java @@ -9,12 +9,19 @@ import org.apache.tomcat.util.http.fileupload.FileUtils; import org.junit.rules.ExternalResource; +import javax.servlet.ServletContainerInitializer; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.net.ServerSocket; import java.net.URI; import java.net.URISyntaxException; +import java.util.Collections; +import java.util.Set; @WebServlet("/*") public class HttpServletServer extends ExternalResource { @@ -64,8 +71,16 @@ private void startServer () throws Exception { Context context = server.addContext("", tmp.getAbsolutePath()); + context.addServletContainerInitializer(new ServletContainerInitializer() { + @Override + public void onStartup(Set> c, ServletContext ctx) throws ServletException { + System.out.println("testing..."); + } + }, Collections.emptySet()); + Tomcat.addServlet( context, "servlet" , servlet); context.addServletMappingDecoded("/*","servlet"); + context.addServletMappingDecoded("/test","servlet"); final Connector connector = new Connector(); connector.setPort(port); @@ -84,15 +99,12 @@ private void stop() { if (server.getServer().getState() != LifecycleState.STOPPED) { server.stop(); } - server.destroy(); - FileUtils.forceDelete(tmp); + FileUtils.forceDelete(tmp); } catch (Exception e) { e.printStackTrace(); } - } - tmp = null; } } \ No newline at end of file diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletContainerInitializerTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletContainerInitializerTest.java new file mode 100644 index 000000000..797cd5150 --- /dev/null +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletContainerInitializerTest.java @@ -0,0 +1,34 @@ +package com.nr.agent.security.instrumentation.servlet24; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Iterator; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) +public class ServletContainerInitializerTest { + @ClassRule + public static HttpServletServer server = new HttpServletServer(); + + @Test + public void testURLMappings() { + String handler = "com.nr.agent.security.instrumentation.servlet24.HttpTestServlet"; + String method = "*"; + Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); + + Assert.assertTrue("URL Mappings", mappings.hasNext()); + ApplicationURLMapping mapping1 = mappings.next(); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); + + Assert.assertTrue("URL Mappings", mappings.hasNext()); + ApplicationURLMapping mapping2 = mappings.next(); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); + } +} diff --git a/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java b/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java index aa32dba10..3ae9792d9 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java +++ b/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java @@ -126,7 +126,7 @@ public static void gatherURLMappings(ServletContext servletContext) { for (ServletRegistration servletRegistration : servletRegistrations.values()) { for (String s : servletRegistration.getMappings()) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, s)); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, s, servletRegistration.getClassName())); } } } catch (Exception e){ diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletContainerInitializer_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletContainerInitializer_Instrumentation.java index 0e3a888bc..65904cf96 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletContainerInitializer_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/ServletContainerInitializer_Instrumentation.java @@ -1,10 +1,12 @@ package jakarta.servlet; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import com.newrelic.agent.security.instrumentation.servlet5.HttpServletHelper; import java.util.Set; -//@Weave(type = MatchType.Interface, originalName = "jakarta.servlet.ServletContainerInitializer") +@Weave(type = MatchType.Interface, originalName = "jakarta.servlet.ServletContainerInitializer") public class ServletContainerInitializer_Instrumentation { public void onStartup(Set> var1, ServletContext var2) throws ServletException { try { diff --git a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpServletServer.java b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpServletServer.java index 958f3eb0a..e45ae3c5d 100644 --- a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpServletServer.java +++ b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpServletServer.java @@ -1,5 +1,8 @@ package com.nr.agent.security.instrumentation.servlet5; +import jakarta.servlet.ServletContainerInitializer; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import org.apache.catalina.Context; import org.apache.catalina.startup.Tomcat; @@ -14,6 +17,8 @@ import java.net.ServerSocket; import java.net.URI; import java.net.URISyntaxException; +import java.util.Collections; +import java.util.Set; @WebServlet("/*") public class HttpServletServer extends ExternalResource { @@ -59,8 +64,16 @@ private void startServer () throws Exception { server.setBaseDir(tmp.getAbsolutePath()); Context context = server.addContext("", tmp.getAbsolutePath()); + context.addServletContainerInitializer(new ServletContainerInitializer() { + @Override + public void onStartup(Set> c, ServletContext ctx) throws ServletException { + System.out.println("testing..."); + } + }, Collections.emptySet()); + Tomcat.addServlet( context, "servlet" , servlet); context.addServletMappingDecoded("/*","servlet"); + context.addServletMappingDecoded("/test","servlet"); final Connector connector = new Connector(); connector.setPort(port); diff --git a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java new file mode 100644 index 000000000..125c81fba --- /dev/null +++ b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java @@ -0,0 +1,34 @@ +package com.nr.agent.security.instrumentation.servlet5; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Iterator; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = { "jakarta.servlet", "com.newrelic.agent.security.instrumentation.servlet5" }) +public class ServletContainerInitializerTest { + @ClassRule + public static HttpServletServer server = new HttpServletServer(); + + @Test + public void testURLMappings() { + String handler = "com.nr.agent.security.instrumentation.servlet5.HttpTestServlet"; + String method = "*"; + Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); + + Assert.assertTrue("URL Mappings", mappings.hasNext()); + ApplicationURLMapping mapping1 = mappings.next(); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); + + Assert.assertTrue("URL Mappings", mappings.hasNext()); + ApplicationURLMapping mapping2 = mappings.next(); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); + } +} diff --git a/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java b/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java index 479e09e03..c9ee8f79b 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java +++ b/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java @@ -126,7 +126,7 @@ public static void gatherURLMappings(ServletContext servletContext) { for (ServletRegistration servletRegistration : servletRegistrations.values()) { for (String s : servletRegistration.getMappings()) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, s)); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, s, servletRegistration.getClassName())); } } } catch (Exception e){ diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletContainerInitializer_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletContainerInitializer_Instrumentation.java index fd0434a5d..099d3afe5 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletContainerInitializer_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/ServletContainerInitializer_Instrumentation.java @@ -1,10 +1,12 @@ package jakarta.servlet; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import com.newrelic.agent.security.instrumentation.servlet6.HttpServletHelper; import java.util.Set; -//@Weave(type = MatchType.Interface, originalName = "jakarta.servlet.ServletContainerInitializer") +@Weave(type = MatchType.Interface, originalName = "jakarta.servlet.ServletContainerInitializer") public class ServletContainerInitializer_Instrumentation { public void onStartup(Set> var1, ServletContext var2) { try { diff --git a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpServletServer.java b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpServletServer.java index 911f76bbb..f725baa32 100644 --- a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpServletServer.java +++ b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpServletServer.java @@ -1,5 +1,8 @@ package com.nr.agent.security.instrumentation.servlet6; +import jakarta.servlet.ServletContainerInitializer; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import org.apache.catalina.Context; import org.apache.catalina.LifecycleState; @@ -15,6 +18,8 @@ import java.net.ServerSocket; import java.net.URI; import java.net.URISyntaxException; +import java.util.Collections; +import java.util.Set; @WebServlet("/*") public class HttpServletServer extends ExternalResource { @@ -59,8 +64,16 @@ private void startServer () throws Exception { server.setBaseDir(tmp.getAbsolutePath()); Context context = server.addContext("", tmp.getAbsolutePath()); + context.addServletContainerInitializer(new ServletContainerInitializer() { + @Override + public void onStartup(Set> c, ServletContext ctx) throws ServletException { + System.out.println("testing..."); + } + }, Collections.emptySet()); + Tomcat.addServlet( context, "servlet" , servlet); context.addServletMappingDecoded("/*","servlet"); + context.addServletMappingDecoded("/test","servlet"); final Connector connector = new Connector(); connector.setPort(port); diff --git a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java new file mode 100644 index 000000000..04c224897 --- /dev/null +++ b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java @@ -0,0 +1,34 @@ +package com.nr.agent.security.instrumentation.servlet6; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Iterator; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = { "jakarta.servlet", "com.newrelic.agent.security.instrumentation.servlet6" }) +public class ServletContainerInitializerTest { + @ClassRule + public static HttpServletServer server = new HttpServletServer(); + + @Test + public void testURLMappings() { + String handler = "com.nr.agent.security.instrumentation.servlet6.HttpTestServlet"; + String method = "*"; + Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); + + Assert.assertTrue("URL Mappings", mappings.hasNext()); + ApplicationURLMapping mapping1 = mappings.next(); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); + + Assert.assertTrue("URL Mappings", mappings.hasNext()); + ApplicationURLMapping mapping2 = mappings.next(); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); + } +} diff --git a/instrumentation-security/spring-webflux/build.gradle b/instrumentation-security/spring-webflux/build.gradle index 90c8f5746..492d134f9 100644 --- a/instrumentation-security/spring-webflux/build.gradle +++ b/instrumentation-security/spring-webflux/build.gradle @@ -7,6 +7,9 @@ dependencies { implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation("org.springframework:spring-webflux:5.0.0.RELEASE") + testImplementation("org.springframework:spring-context:5.0.0.RELEASE") + testImplementation("org.springframework:spring-aop:5.0.0.RELEASE") + testImplementation("jakarta.servlet:jakarta.servlet-api:4.0.2") } jar { diff --git a/instrumentation-security/spring-webflux/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java b/instrumentation-security/spring-webflux/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java new file mode 100644 index 000000000..e9c1e1706 --- /dev/null +++ b/instrumentation-security/spring-webflux/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java @@ -0,0 +1,61 @@ +package com.nr.agent.security.instrumentation.spring.webmvc; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; + +import java.util.HashMap; +import java.util.Set; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = {"org.springframework.web.reactive"}) +public class APIEndpointTest { + + TestHandlerMethodMapping handlerMapping = new TestHandlerMethodMapping(); + private final String handler = TestMappings.class.getName(); + + private final static HashMap map = new HashMap<>(); + + @BeforeClass + public static void addMappings() { + map.put("/postMapping", "POST"); + map.put("/requestMapping", "GET"); + map.put("/getMapping", "GET"); + map.put("/patchMapping", "PATCH"); + map.put("/putMapping", "PUT"); + map.put("/deleteMapping", "DELETE"); + } + + @Test + public void testAPIEndpointDetection() { + handlerMapping.addMapping(new TestMappings()); + + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertEquals(6, mappings.size()); + + for (ApplicationURLMapping mapping: mappings) { + Assert.assertNotNull(mapping); + assertMapping(mapping); + } + + } + + private void assertMapping(ApplicationURLMapping actualMapping) { + String path = actualMapping.getPath(); + String method = map.get(path); + Assert.assertEquals(method, actualMapping.getMethod()); + Assert.assertEquals(handler, actualMapping.getHandler()); + } +} + +class TestHandlerMethodMapping extends RequestMappingHandlerMapping { + public void addMapping(Object handler) { + super.detectHandlerMethods(handler); + } +} \ No newline at end of file diff --git a/instrumentation-security/spring-webflux/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java b/instrumentation-security/spring-webflux/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java new file mode 100644 index 000000000..c95ca87eb --- /dev/null +++ b/instrumentation-security/spring-webflux/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java @@ -0,0 +1,48 @@ +package com.nr.agent.security.instrumentation.spring.webmvc;/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + + +public class TestMappings { + + @RequestMapping(value = "/requestMapping", method = RequestMethod.GET) + public String testRequest() { + return "From Request Mapping"; + } + + @GetMapping(value = "/getMapping") + public String testGet() { + return "From Get Mapping"; + } + + @PostMapping(value = "/postMapping") + public String testPost() { + return "From Post Mapping"; + } + + @PatchMapping(value = "/patchMapping") + public String testPatch() { + return "From Patch Mapping"; + } + + @PutMapping(value = "/putMapping") + public String testPut() { + return "From Put Mapping"; + } + + @DeleteMapping(value = "/deleteMapping") + public String testDelete() { + return "From Delete Mapping"; + } +} diff --git a/instrumentation-security/spring-webmvc-3.1.0/build.gradle b/instrumentation-security/spring-webmvc-3.1.0/build.gradle index ae3d6ba5f..1270f47a9 100644 --- a/instrumentation-security/spring-webmvc-3.1.0/build.gradle +++ b/instrumentation-security/spring-webmvc-3.1.0/build.gradle @@ -7,6 +7,8 @@ dependencies { implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation("org.springframework:spring-webmvc:3.1.0.RELEASE") + testImplementation("jakarta.servlet:jakarta.servlet-api:4.0.2") + testImplementation("org.springframework:spring-web:3.1.0.RELEASE") } jar { diff --git a/instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java b/instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java new file mode 100644 index 000000000..8c10e6923 --- /dev/null +++ b/instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java @@ -0,0 +1,63 @@ +package com.nr.agent.security.instrumentation.spring.webmvc; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +import java.util.HashMap; +import java.util.Set; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = {"org.springframework.web.servlet"}) +public class APIEndpointTest { + + TestHandlerMethodMapping methodMapping = new TestHandlerMethodMapping(); + + + private final String handler = TestMappings.class.getName(); + + private final static HashMap map = new HashMap<>(); + + + @BeforeClass + public static void addMappings() { + map.put("/postMapping", "POST"); + map.put("/requestMapping", "GET"); + map.put("/putMapping", "PUT"); + map.put("/deleteMapping", "DELETE"); + } + + @Test + public void testAPIEndpointDetection() { + methodMapping.addMapping(new TestMappings()); + + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertEquals(4, mappings.size()); + + for (ApplicationURLMapping mapping: mappings) { + Assert.assertNotNull(mapping); + assertMapping(mapping); + } + + } + + private void assertMapping(ApplicationURLMapping actualMapping) { + String path = actualMapping.getPath(); + String method = map.get(path); + Assert.assertEquals(method, actualMapping.getMethod()); + Assert.assertEquals(handler, actualMapping.getHandler()); + } +} + +class TestHandlerMethodMapping extends RequestMappingHandlerMapping { + + public void addMapping(Object handler) { + super.detectHandlerMethods(handler); + } +} diff --git a/instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java b/instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java new file mode 100644 index 000000000..8a0b25b14 --- /dev/null +++ b/instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java @@ -0,0 +1,34 @@ +package com.nr.agent.security.instrumentation.spring.webmvc;/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +public class TestMappings { + + @RequestMapping(value = "/requestMapping", method = RequestMethod.GET) + public String testRequest() { + return "From Request Mapping"; + } + + @RequestMapping(value = "/postMapping", method = RequestMethod.POST) + public String testPost() { + return "From Post Mapping"; + } + + @RequestMapping(value = "/putMapping", method = RequestMethod.PUT) + public String testPut() { + return "From Put Mapping"; + } + + @RequestMapping(value = "/deleteMapping", method = RequestMethod.DELETE) + public String testDelete() { + return "From Delete Mapping"; + } +} diff --git a/instrumentation-security/spring-webmvc-5.3.0/build.gradle b/instrumentation-security/spring-webmvc-5.3.0/build.gradle index 678ca7ac0..0b657eaf3 100644 --- a/instrumentation-security/spring-webmvc-5.3.0/build.gradle +++ b/instrumentation-security/spring-webmvc-5.3.0/build.gradle @@ -7,6 +7,8 @@ dependencies { implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation("org.springframework:spring-webmvc:5.3.0") + testImplementation("org.springframework:spring-web:5.3.0") + testImplementation("jakarta.servlet:jakarta.servlet-api:4.0.2") } jar { diff --git a/instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java b/instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java new file mode 100644 index 000000000..d1b94dc24 --- /dev/null +++ b/instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java @@ -0,0 +1,63 @@ +package com.nr.agent.security.instrumentation.spring.webmvc; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +import java.util.HashMap; +import java.util.Set; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = {"org.springframework.web.servlet"}) +public class APIEndpointTest { + + TestHandlerMethodMapping methodMapping = new TestHandlerMethodMapping(); + private final String handler = TestMappings.class.getName(); + + private final static HashMap map = new HashMap<>(); + + + @BeforeClass + public static void addMappings() { + map.put("/postMapping", "POST"); + map.put("/requestMapping", "GET"); + map.put("/getMapping", "GET"); + map.put("/patchMapping", "PATCH"); + map.put("/putMapping", "PUT"); + map.put("/deleteMapping", "DELETE"); + } + + @Test + public void testAPIEndpointDetection() { + methodMapping.addMapping(new TestMappings()); + + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertEquals(6, mappings.size()); + + for (ApplicationURLMapping mapping: mappings) { + Assert.assertNotNull(mapping); + assertMapping(mapping); + } + + } + + private void assertMapping(ApplicationURLMapping actualMapping) { + String path = actualMapping.getPath(); + String method = map.get(path); + Assert.assertEquals(method, actualMapping.getMethod()); + Assert.assertEquals(handler, actualMapping.getHandler()); + } +} + +class TestHandlerMethodMapping extends RequestMappingHandlerMapping { + + public void addMapping(Object handler) { + super.detectHandlerMethods(handler); + } +} \ No newline at end of file diff --git a/instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java b/instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java new file mode 100644 index 000000000..fbba258fd --- /dev/null +++ b/instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/TestMappings.java @@ -0,0 +1,49 @@ +package com.nr.agent.security.instrumentation.spring.webmvc;/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +public class TestMappings { + + @RequestMapping(value = "/requestMapping", method = RequestMethod.GET) + public String testRequest() { + return "From Request Mapping"; + } + + @GetMapping(value = "/getMapping") + public String testGet() { + return "From Get Mapping"; + } + + @PostMapping(value = "/postMapping") + public String testPost() { + return "From Post Mapping"; + } + + @PatchMapping(value = "/patchMapping") + public String testPatch() { + return "From Patch Mapping"; + } + + @PutMapping(value = "/putMapping") + public String testPut() { + return "From Put Mapping"; + } + + @DeleteMapping(value = "/deleteMapping") + public String testDelete() { + return "From Delete Mapping"; + } +} From 951496f0e4b8879963dc4fb3bc2af8750d39140a Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Mon, 26 Feb 2024 18:37:10 +0530 Subject: [PATCH 036/124] [NR-223398] API endpoint support & unit tests for Embed Apache-Tomcat --- .../apache-tomcat-10/build.gradle | 22 ++++ .../apache/tomcat10/HttpServletHelper.java | 55 +++++++++ .../StandardContext_Instrumentation.java | 22 ++++ .../tomcat10/APIEndpointTest.java | 73 ++++++++++++ .../tomcat10/HttpServletServer.java | 106 ++++++++++++++++++ .../apache-tomcat-7/build.gradle | 22 ++++ .../apache/tomcat7/HttpServletHelper.java | 55 +++++++++ .../StandardContext_Instrumentation.java | 22 ++++ .../tomcat7/APIEndpointTest.java | 73 ++++++++++++ .../tomcat7/HttpServletServer.java | 106 ++++++++++++++++++ settings.gradle | 5 +- 11 files changed, 560 insertions(+), 1 deletion(-) create mode 100644 instrumentation-security/apache-tomcat-10/build.gradle create mode 100644 instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java create mode 100644 instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/StandardContext_Instrumentation.java create mode 100644 instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java create mode 100644 instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/HttpServletServer.java create mode 100644 instrumentation-security/apache-tomcat-7/build.gradle create mode 100644 instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java create mode 100644 instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/StandardContext_Instrumentation.java create mode 100644 instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java create mode 100644 instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/HttpServletServer.java diff --git a/instrumentation-security/apache-tomcat-10/build.gradle b/instrumentation-security/apache-tomcat-10/build.gradle new file mode 100644 index 000000000..337c0de09 --- /dev/null +++ b/instrumentation-security/apache-tomcat-10/build.gradle @@ -0,0 +1,22 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("org.apache.tomcat.embed:tomcat-embed-core:10.0.0") + implementation("org.apache.tomcat:tomcat-juli:10.0.0") +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.apache-tomcat-10' } +} + +verifyInstrumentation { + passesOnly('org.apache.tomcat.embed:tomcat-embed-core:[10.0.0-M1,)') + fails('org.apache.tomcat.embed:tomcat-embed-core:[7.0.0,10.0.0-M1)') + excludeRegex '.*-(b|gfa|beta|RC)[0-9]*' +} + +site { + title 'Tomcat' + type 'Appserver' +} \ No newline at end of file diff --git a/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java b/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java new file mode 100644 index 000000000..89137ecb2 --- /dev/null +++ b/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java @@ -0,0 +1,55 @@ +package com.newrelic.agent.security.instrumentation.apache.tomcat10; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.api.agent.security.utils.logging.LogLevel; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletRegistration; +import java.util.Collection; +import java.util.Map; + +public class HttpServletHelper { + private static final String EMPTY = ""; + private static final String WILDCARD = "*"; + private static final String NULL = "null"; + private static final String SEPARATOR = "/"; + public static final String APACHE_TOMCAT_10 = "APACHE-TOMCAT-10"; + + public static void gatherURLMappings(ServletContext servletContext) { + try { + Map servletRegistrations = servletContext.getServletRegistrations(); + getJSPMappings(servletContext, SEPARATOR); + + for (ServletRegistration servletRegistration : servletRegistrations.values()) { + for (String mapping : servletRegistration.getMappings()) { + String path = (mapping.startsWith(SEPARATOR) ? EMPTY : SEPARATOR) + mapping; + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path, servletRegistration.getClassName())); + } + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, APACHE_TOMCAT_10, e.getMessage()), e, HttpServletHelper.class.getName()); + } + } + + private static void getJSPMappings(ServletContext servletContext, String dir) { + try { + if(dir.endsWith(SEPARATOR)){ + Collection resourcePaths = servletContext.getResourcePaths(dir); + for (String path : resourcePaths) { + if(path.endsWith(SEPARATOR)) { + getJSPMappings(servletContext, path); + } + else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, (path.startsWith(SEPARATOR) ? EMPTY : SEPARATOR) + path, NULL)); + } + } + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, APACHE_TOMCAT_10, e.getMessage()), e, HttpServletHelper.class.getName()); + } + } +} diff --git a/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/StandardContext_Instrumentation.java b/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/StandardContext_Instrumentation.java new file mode 100644 index 000000000..d49785a9b --- /dev/null +++ b/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/StandardContext_Instrumentation.java @@ -0,0 +1,22 @@ +package com.newrelic.agent.security.instrumentation.apache.tomcat10; + +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import org.apache.catalina.LifecycleException; + +import jakarta.servlet.ServletContext; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.catalina.core.StandardContext") +public abstract class StandardContext_Instrumentation { + + public abstract ServletContext getServletContext(); + + protected synchronized void startInternal() throws LifecycleException { + try { + Weaver.callOriginal(); + } finally { + HttpServletHelper.gatherURLMappings(getServletContext()); + } + } +} diff --git a/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java new file mode 100644 index 000000000..249b1eea7 --- /dev/null +++ b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java @@ -0,0 +1,73 @@ +package com.nr.agent.security.instrumentation.tomcat10; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import org.apache.catalina.servlets.DefaultServlet; +import org.junit.Assert; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = {"com.newrelic.agent.security.instrumentation.apache.tomcat10" }) +public class APIEndpointTest { + @ClassRule + public static HttpServletServer server = new HttpServletServer(); + + private final Map expectedMappings = new HashMap<>(); + + @Before + public void setupEndpoints() { + expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); + expectedMappings.put("/index.jsp", "null"); + expectedMappings.put("/*.jsp", "org.apache.jasper.servlet.JspServlet"); + expectedMappings.put("/", DefaultServlet.class.getName()); + expectedMappings.put("/*.jspx", "org.apache.jasper.servlet.JspServlet"); + } + + @Test + public void testAPIEndpoint() throws Exception { + service(); + + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertNotNull(mappings); + Assert.assertEquals(5, mappings.size()); + for (ApplicationURLMapping mapping : mappings) { + assertMappings(mapping); + } + } + + private void assertMappings(ApplicationURLMapping actualMapping) { + Assert.assertNotNull(actualMapping); + + Assert.assertNotNull(actualMapping.getPath()); + String path = actualMapping.getPath(); + String handler = expectedMappings.get(path); + + Assert.assertNotNull(actualMapping.getMethod()); + Assert.assertNotNull(actualMapping.getHandler()); + + Assert.assertEquals(handler, actualMapping.getHandler()); + Assert.assertEquals("*", actualMapping.getMethod()); + } + @Trace(dispatcher = true) + private void service() throws IOException, URISyntaxException { + URL u = server.getEndPoint("").toURL(); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); + conn.connect(); + conn.getResponseCode(); + } +} diff --git a/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/HttpServletServer.java b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/HttpServletServer.java new file mode 100644 index 000000000..dfeac726a --- /dev/null +++ b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/HttpServletServer.java @@ -0,0 +1,106 @@ +package com.nr.agent.security.instrumentation.tomcat10; + +import org.apache.catalina.Context; +import org.apache.catalina.LifecycleState; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory; +import org.apache.tomcat.util.http.fileupload.FileUtils; +import org.junit.rules.ExternalResource; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.URI; +import java.net.URISyntaxException; + +public class HttpServletServer extends ExternalResource { + + private final int port; + private Tomcat server; + private final String webappDirLocation = "./src/test/webapp/"; + private File tmp = new File(webappDirLocation); + public HttpServletServer() { + this.port = getRandomPort(); + } + + @Override + protected void before() throws Throwable { + startServer(); + } + + @Override + protected void after() { + stop(); + } + + private static int getRandomPort() { + try (ServerSocket socket = new ServerSocket(0)){ + return socket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Unable to allocate ephemeral port "); + } + } + + private void startServer () throws Exception { + TomcatURLStreamHandlerFactory.disable(); + createFile(); + + server = new Tomcat(); + server.setPort(port); + + server.setBaseDir(webappDirLocation); + server.addWebapp("", tmp.getAbsolutePath()); + + Context context = server.addContext("/tmp", tmp.getAbsolutePath()); + Tomcat.addServlet(context, "servlet", new HttpServlet() { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + System.out.println("get API handler"); + super.doGet(req, resp); + } + }); + context.setAddWebinfClassesResources(true); + context.addWelcomeFile("/index.jsp"); + context.addServletMappingDecoded("/servlet/*","servlet"); + + server.getConnector(); + server.start(); + } + + public URI getEndPoint(String path) throws URISyntaxException { + return new URI("http://localhost:" + port + "/" + path); + } + private void createFile() { + File indexFile = new File(webappDirLocation + "index.jsp"); + try { + if (tmp.mkdir() && indexFile.createNewFile()) { + BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile)); + writer.append("Hello World!"); + writer.flush(); + writer.close(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + private void stop() { + if (server.getServer() != null && server.getServer().getState() != LifecycleState.DESTROYED) { + try { + if (server.getServer().getState() != LifecycleState.STOPPED) { + server.stop(); + } + server.destroy(); + FileUtils.forceDelete(tmp); + } catch (Exception e) { + e.printStackTrace(); + } + } + tmp = null; + } +} \ No newline at end of file diff --git a/instrumentation-security/apache-tomcat-7/build.gradle b/instrumentation-security/apache-tomcat-7/build.gradle new file mode 100644 index 000000000..8614e74a0 --- /dev/null +++ b/instrumentation-security/apache-tomcat-7/build.gradle @@ -0,0 +1,22 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("org.apache.tomcat.embed:tomcat-embed-core:8.0.1") + implementation("org.apache.tomcat:tomcat-juli:8.0.1") +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.apache-tomcat-7' } +} + +verifyInstrumentation { + passesOnly 'org.apache.tomcat.embed:tomcat-embed-core:[7.0.0,10.0.0-M1)' + fails('org.apache.tomcat.embed:tomcat-embed-core:[10.0.0,)') + excludeRegex '.*-(b|gfa|beta|RC)[0-9]*' +} + +site { + title 'Tomcat' + type 'Appserver' +} \ No newline at end of file diff --git a/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java b/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java new file mode 100644 index 000000000..7bbc8ff60 --- /dev/null +++ b/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java @@ -0,0 +1,55 @@ +package com.newrelic.agent.security.instrumentation.apache.tomcat7; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.api.agent.security.utils.logging.LogLevel; + +import javax.servlet.ServletContext; +import javax.servlet.ServletRegistration; +import java.util.Collection; +import java.util.Map; + +public class HttpServletHelper { + private static final String EMPTY = ""; + private static final String WILDCARD = "*"; + private static final String NULL = "null"; + private static final String SEPARATOR = "/"; + public static final String APACHE_TOMCAT_7 = "APACHE-TOMCAT-7"; + + public static void gatherURLMappings(ServletContext servletContext) { + try { + Map servletRegistrations = servletContext.getServletRegistrations(); + getJSPMappings(servletContext, SEPARATOR); + + for (ServletRegistration servletRegistration : servletRegistrations.values()) { + for (String mapping : servletRegistration.getMappings()) { + String path = (mapping.startsWith(SEPARATOR) ? EMPTY : SEPARATOR) + mapping; + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path, servletRegistration.getClassName())); + } + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, APACHE_TOMCAT_7, e.getMessage()), e, HttpServletHelper.class.getName()); + } + } + + private static void getJSPMappings(ServletContext servletContext, String dir) { + try { + if(dir.endsWith(SEPARATOR)){ + Collection resourcePaths = servletContext.getResourcePaths(dir); + for (String path : resourcePaths) { + if(path.endsWith(SEPARATOR)) { + getJSPMappings(servletContext, path); + } + else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, (path.startsWith(SEPARATOR) ? EMPTY : SEPARATOR) + path, NULL)); + } + } + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, APACHE_TOMCAT_7, e.getMessage()), e, HttpServletHelper.class.getName()); + } + } +} diff --git a/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/StandardContext_Instrumentation.java b/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/StandardContext_Instrumentation.java new file mode 100644 index 000000000..61faec528 --- /dev/null +++ b/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/StandardContext_Instrumentation.java @@ -0,0 +1,22 @@ +package com.newrelic.agent.security.instrumentation.apache.tomcat7; + +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import org.apache.catalina.LifecycleException; + +import javax.servlet.ServletContext; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.catalina.core.StandardContext") +public abstract class StandardContext_Instrumentation { + + public abstract ServletContext getServletContext(); + + protected synchronized void startInternal() throws LifecycleException { + try { + Weaver.callOriginal(); + } finally { + HttpServletHelper.gatherURLMappings(getServletContext()); + } + } +} diff --git a/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java new file mode 100644 index 000000000..b5ca8f3a2 --- /dev/null +++ b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java @@ -0,0 +1,73 @@ +package com.nr.agent.security.instrumentation.tomcat7; + +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import org.apache.catalina.servlets.DefaultServlet; +import org.junit.Assert; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +@RunWith(SecurityInstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = {"com.newrelic.agent.security.instrumentation.apache.tomcat7" }) +public class APIEndpointTest { + @ClassRule + public static HttpServletServer server = new HttpServletServer(); + + private final Map expectedMappings = new HashMap<>(); + + @Before + public void setupEndpoints() { + expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); + expectedMappings.put("/index.jsp", "null"); + expectedMappings.put("/*.jsp", "org.apache.jasper.servlet.JspServlet"); + expectedMappings.put("/", DefaultServlet.class.getName()); + expectedMappings.put("/*.jspx", "org.apache.jasper.servlet.JspServlet"); + } + + @Test + public void testAPIEndpoint() throws Exception { + service(); + + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertNotNull(mappings); + Assert.assertEquals(5, mappings.size()); + for (ApplicationURLMapping mapping : mappings) { + assertMappings(mapping); + } + } + + private void assertMappings(ApplicationURLMapping actualMapping) { + Assert.assertNotNull(actualMapping); + + Assert.assertNotNull(actualMapping.getPath()); + String path = actualMapping.getPath(); + String handler = expectedMappings.get(path); + + Assert.assertNotNull(actualMapping.getMethod()); + Assert.assertNotNull(actualMapping.getHandler()); + + Assert.assertEquals(handler, actualMapping.getHandler()); + Assert.assertEquals("*", actualMapping.getMethod()); + } + @Trace(dispatcher = true) + private void service() throws IOException, URISyntaxException { + URL u = server.getEndPoint("").toURL(); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); + conn.connect(); + conn.getResponseCode(); + } +} diff --git a/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/HttpServletServer.java b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/HttpServletServer.java new file mode 100644 index 000000000..e355d051d --- /dev/null +++ b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/HttpServletServer.java @@ -0,0 +1,106 @@ +package com.nr.agent.security.instrumentation.tomcat7; + +import org.apache.catalina.Context; +import org.apache.catalina.LifecycleState; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory; +import org.apache.tomcat.util.http.fileupload.FileUtils; +import org.junit.rules.ExternalResource; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.URI; +import java.net.URISyntaxException; + +public class HttpServletServer extends ExternalResource { + + private final int port; + private Tomcat server; + private final String webappDirLocation = "./src/test/webapp/"; + private File tmp = new File(webappDirLocation); + public HttpServletServer() { + this.port = getRandomPort(); + } + + @Override + protected void before() throws Throwable { + startServer(); + } + + @Override + protected void after() { + stop(); + } + + private static int getRandomPort() { + try (ServerSocket socket = new ServerSocket(0)){ + return socket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Unable to allocate ephemeral port "); + } + } + + private void startServer () throws Exception { + TomcatURLStreamHandlerFactory.disable(); + createFile(); + + server = new Tomcat(); + server.setPort(port); + + server.setBaseDir(webappDirLocation); + server.addWebapp("", tmp.getAbsolutePath()); + + Context context = server.addContext("/tmp", tmp.getAbsolutePath()); + Tomcat.addServlet(context, "servlet", new HttpServlet() { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + System.out.println("get API handler"); + super.doGet(req, resp); + } + }); + context.setAddWebinfClassesResources(true); + context.addWelcomeFile("/index.jsp"); + context.addServletMapping("/servlet/*","servlet"); + + server.getConnector(); + server.start(); + } + + public URI getEndPoint(String path) throws URISyntaxException { + return new URI("http://localhost:" + port + "/" + path); + } + private void createFile() { + File indexFile = new File(webappDirLocation + "index.jsp"); + try { + if (tmp.mkdir() && indexFile.createNewFile()) { + BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile)); + writer.append("Hello World!"); + writer.flush(); + writer.close(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + private void stop() { + if (server.getServer() != null && server.getServer().getState() != LifecycleState.DESTROYED) { + try { + if (server.getServer().getState() != LifecycleState.STOPPED) { + server.stop(); + } + server.destroy(); + FileUtils.forceDelete(tmp); + } catch (Exception e) { + e.printStackTrace(); + } + } + tmp = null; + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index beb954e25..223b68388 100644 --- a/settings.gradle +++ b/settings.gradle @@ -167,6 +167,8 @@ include 'instrumentation:grpc-1.40.0' include 'instrumentation:play-2.4' include 'instrumentation:play-2.6' include 'instrumentation:play-2.13_2.7' +include 'instrumentation:apache-tomcat-7' +include 'instrumentation:apache-tomcat-10' //include 'instrumentation:ning-async-http-client-1.1.0' //include 'instrumentation:ning-async-http-client-1.6.1' @@ -181,4 +183,5 @@ include 'instrumentation:play-2.13_2.7' //include 'instrumentation:spymemcached-2.12.0' //include 'instrumentation:jetty-12' //include 'instrumentation:mule-3.7' -//include 'instrumentation:mule-3.6' \ No newline at end of file +//include 'instrumentation:mule-3.6' + From 07cc256d88e3f5aea3be572f19ec798ecc191d5a Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 26 Feb 2024 21:38:20 +0530 Subject: [PATCH 037/124] update imports --- .../request/mapper/mount/MountMapper_Instrumentation.java | 2 +- .../request/mapper/mount/MountedMapper_Instrumentation.java | 2 +- .../request/mapper/mount/PackageMapper_Instrumentation.java | 2 +- .../core/request/mapper/MountedMapper_Instrumentation.java | 2 +- .../core/request/mapper/PackageMapper_Instrumentation.java | 2 +- .../core/request/mapper/MountedMapper_Instrumentation.java | 2 +- .../core/request/mapper/PackageMapper_Instrumentation.java | 2 +- .../grails/commons/DefaultGrailsController_Instrumentation.java | 2 +- .../grails/commons/DefaultGrailsController_Instrumentation.java | 2 +- .../grails/core/DefaultGrailsController_Instrumentation.java | 2 +- .../server/internal/JerseyResourceContext_Instrumentation.java | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/MountMapper_Instrumentation.java b/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/MountMapper_Instrumentation.java index 0f73a6cf9..ed8f77cad 100644 --- a/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/MountMapper_Instrumentation.java +++ b/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/MountMapper_Instrumentation.java @@ -2,7 +2,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; -import com.nr.instrumentation.security.apache.wicket6.WicketHelper; +import com.newrelic.agent.security.instrumentation.apache.wicket6.WicketHelper; import org.apache.wicket.request.IRequestMapper; @Weave(type = MatchType.ExactClass, originalName = "org.apache.wicket.request.mapper.mount.MountMapper") diff --git a/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/MountedMapper_Instrumentation.java b/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/MountedMapper_Instrumentation.java index 1c065a47c..2f9f1aba0 100644 --- a/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/MountedMapper_Instrumentation.java +++ b/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/MountedMapper_Instrumentation.java @@ -2,7 +2,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; -import com.nr.instrumentation.security.apache.wicket6.WicketHelper; +import com.newrelic.agent.security.instrumentation.apache.wicket6.WicketHelper; import org.apache.wicket.request.component.IRequestablePage; import org.apache.wicket.request.mapper.parameter.IPageParametersEncoder; import org.apache.wicket.util.IProvider; diff --git a/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/PackageMapper_Instrumentation.java b/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/PackageMapper_Instrumentation.java index 88f7c1af5..a114120c2 100644 --- a/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/PackageMapper_Instrumentation.java +++ b/instrumentation-security/apache-wicket-6.4/src/main/java/org/apache/wicket/request/mapper/mount/PackageMapper_Instrumentation.java @@ -2,7 +2,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; -import com.nr.instrumentation.security.apache.wicket6.WicketHelper; +import com.newrelic.agent.security.instrumentation.apache.wicket6.WicketHelper; import org.apache.wicket.request.mapper.parameter.IPageParametersEncoder; import org.apache.wicket.util.lang.PackageName; diff --git a/instrumentation-security/apache-wicket-7.0/src/main/java/org/apache/wicket/core/request/mapper/MountedMapper_Instrumentation.java b/instrumentation-security/apache-wicket-7.0/src/main/java/org/apache/wicket/core/request/mapper/MountedMapper_Instrumentation.java index d8a9ea7ca..61aea584c 100644 --- a/instrumentation-security/apache-wicket-7.0/src/main/java/org/apache/wicket/core/request/mapper/MountedMapper_Instrumentation.java +++ b/instrumentation-security/apache-wicket-7.0/src/main/java/org/apache/wicket/core/request/mapper/MountedMapper_Instrumentation.java @@ -2,7 +2,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; -import com.nr.instrumentation.security.apache.wicket7.WicketHelper; +import com.newrelic.agent.security.instrumentation.apache.wicket7.WicketHelper; import org.apache.wicket.request.component.IRequestablePage; import org.apache.wicket.request.mapper.parameter.IPageParametersEncoder; import org.apache.wicket.util.IProvider; diff --git a/instrumentation-security/apache-wicket-7.0/src/main/java/org/apache/wicket/core/request/mapper/PackageMapper_Instrumentation.java b/instrumentation-security/apache-wicket-7.0/src/main/java/org/apache/wicket/core/request/mapper/PackageMapper_Instrumentation.java index 648807be1..d440ec102 100644 --- a/instrumentation-security/apache-wicket-7.0/src/main/java/org/apache/wicket/core/request/mapper/PackageMapper_Instrumentation.java +++ b/instrumentation-security/apache-wicket-7.0/src/main/java/org/apache/wicket/core/request/mapper/PackageMapper_Instrumentation.java @@ -2,7 +2,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; -import com.nr.instrumentation.security.apache.wicket7.WicketHelper; +import com.newrelic.agent.security.instrumentation.apache.wicket7.WicketHelper; import org.apache.wicket.request.mapper.parameter.IPageParametersEncoder; import org.apache.wicket.util.lang.PackageName; diff --git a/instrumentation-security/apache-wicket-8.0/src/main/java/org/apache/wicket/core/request/mapper/MountedMapper_Instrumentation.java b/instrumentation-security/apache-wicket-8.0/src/main/java/org/apache/wicket/core/request/mapper/MountedMapper_Instrumentation.java index e0f31197a..08e64a5b6 100644 --- a/instrumentation-security/apache-wicket-8.0/src/main/java/org/apache/wicket/core/request/mapper/MountedMapper_Instrumentation.java +++ b/instrumentation-security/apache-wicket-8.0/src/main/java/org/apache/wicket/core/request/mapper/MountedMapper_Instrumentation.java @@ -2,7 +2,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; -import com.nr.instrumentation.security.apache.wicket8.WicketHelper; +import com.newrelic.agent.security.instrumentation.apache.wicket8.WicketHelper; import org.apache.wicket.request.component.IRequestablePage; import org.apache.wicket.request.mapper.parameter.IPageParametersEncoder; diff --git a/instrumentation-security/apache-wicket-8.0/src/main/java/org/apache/wicket/core/request/mapper/PackageMapper_Instrumentation.java b/instrumentation-security/apache-wicket-8.0/src/main/java/org/apache/wicket/core/request/mapper/PackageMapper_Instrumentation.java index 873adf232..5c2d9d9b4 100644 --- a/instrumentation-security/apache-wicket-8.0/src/main/java/org/apache/wicket/core/request/mapper/PackageMapper_Instrumentation.java +++ b/instrumentation-security/apache-wicket-8.0/src/main/java/org/apache/wicket/core/request/mapper/PackageMapper_Instrumentation.java @@ -2,7 +2,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; -import com.nr.instrumentation.security.apache.wicket8.WicketHelper; +import com.newrelic.agent.security.instrumentation.apache.wicket8.WicketHelper; import org.apache.wicket.request.mapper.parameter.IPageParametersEncoder; import org.apache.wicket.util.lang.PackageName; diff --git a/instrumentation-security/grails-1.3/src/main/java/org/codehaus/groovy/grails/commons/DefaultGrailsController_Instrumentation.java b/instrumentation-security/grails-1.3/src/main/java/org/codehaus/groovy/grails/commons/DefaultGrailsController_Instrumentation.java index eae553ef7..e936a10c6 100644 --- a/instrumentation-security/grails-1.3/src/main/java/org/codehaus/groovy/grails/commons/DefaultGrailsController_Instrumentation.java +++ b/instrumentation-security/grails-1.3/src/main/java/org/codehaus/groovy/grails/commons/DefaultGrailsController_Instrumentation.java @@ -4,7 +4,7 @@ import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.WeaveAllConstructors; import com.newrelic.api.agent.weaver.Weaver; -import com.nr.instrumentation.security.grails13.GrailsHelper; +import com.newrelic.agent.security.instrumentation.grails13.GrailsHelper; import java.util.Map; diff --git a/instrumentation-security/grails-2.0/src/main/java/org/codehaus/groovy/grails/commons/DefaultGrailsController_Instrumentation.java b/instrumentation-security/grails-2.0/src/main/java/org/codehaus/groovy/grails/commons/DefaultGrailsController_Instrumentation.java index ae6902a92..8f88fb90b 100644 --- a/instrumentation-security/grails-2.0/src/main/java/org/codehaus/groovy/grails/commons/DefaultGrailsController_Instrumentation.java +++ b/instrumentation-security/grails-2.0/src/main/java/org/codehaus/groovy/grails/commons/DefaultGrailsController_Instrumentation.java @@ -3,7 +3,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.nr.instrumentation.security.grails2.GrailsHelper; +import com.newrelic.agent.security.instrumentation.grails2.GrailsHelper; import java.util.Map; diff --git a/instrumentation-security/grails-3.0/src/main/java/org/grails/core/DefaultGrailsController_Instrumentation.java b/instrumentation-security/grails-3.0/src/main/java/org/grails/core/DefaultGrailsController_Instrumentation.java index 91fe02fcd..a0f86b79e 100644 --- a/instrumentation-security/grails-3.0/src/main/java/org/grails/core/DefaultGrailsController_Instrumentation.java +++ b/instrumentation-security/grails-3.0/src/main/java/org/grails/core/DefaultGrailsController_Instrumentation.java @@ -4,7 +4,7 @@ import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.WeaveAllConstructors; import com.newrelic.api.agent.weaver.Weaver; -import com.nr.instrumentation.security.grails3.GrailsHelper; +import com.newrelic.agent.security.instrumentation.grails3.GrailsHelper; import java.lang.reflect.Method; import java.util.Map; diff --git a/instrumentation-security/jersey/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext_Instrumentation.java b/instrumentation-security/jersey/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext_Instrumentation.java index 149fc5cca..ef6eb3234 100644 --- a/instrumentation-security/jersey/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext_Instrumentation.java +++ b/instrumentation-security/jersey/src/main/java/org/glassfish/jersey/server/internal/JerseyResourceContext_Instrumentation.java @@ -3,7 +3,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.nr.instrumentation.security.jersey.JerseyHelper; +import com.newrelic.agent.security.instrumentation.jersey.JerseyHelper; import org.glassfish.jersey.server.model.ResourceModel; From 6a957b858f4f8bc6681c450085d64d00ec54c1d3 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 27 Feb 2024 10:57:17 +0530 Subject: [PATCH 038/124] Remove dispatcher true from wevaved methods --- .../scala/spray/can/server/ServerFrontend_Instrumentation.java | 2 +- .../src/main/scala/spray/routing/SprayRoutingHttpServer.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/server/ServerFrontend_Instrumentation.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/server/ServerFrontend_Instrumentation.java index 16eb7b704..6dd9a3fd5 100644 --- a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/server/ServerFrontend_Instrumentation.java +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/server/ServerFrontend_Instrumentation.java @@ -16,7 +16,7 @@ @Weave(originalName = "spray.can.server.ServerFrontend$$anon$2$$anon$1") public class ServerFrontend_Instrumentation { - @Trace(dispatcher = true) + public void spray$can$server$ServerFrontend$$anon$$anon$$openNewRequest(final HttpRequest request, final boolean closeAfterResponseCompletion, final RequestState state) { boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribName()); diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java index 7fa994c8d..fe4c0f476 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/routing/SprayRoutingHttpServer.java @@ -19,7 +19,6 @@ @Weave(type = MatchType.ExactClass, originalName = "spray.routing.HttpServiceBase$class") public class SprayRoutingHttpServer { - @Trace(dispatcher = true) public static final void runSealedRoute$1(final HttpServiceBase $this, final RequestContext ctx, final PartialFunction sealedExceptionHandler$1, final Function1 sealedRoute$1) { boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribName()); if (isLockAcquired) { From c370c9c504325266d4a35ca2144129633e5ae0d3 Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:33:16 +0530 Subject: [PATCH 039/124] API endpoint support for Mule server (#196) --- .../instrumentation/mule36/MuleHelper.java | 28 +++++++++++++++++++ .../AbstractPipeline_Instrumentation.java | 27 ++++++++++++++++++ ...vokerMessageProcessor_Instrumentation.java | 20 +++++++++++++ .../instrumentation/mule37/MuleHelper.java | 28 +++++++++++++++++++ .../AbstractPipeline_Instrumentation.java | 27 ++++++++++++++++++ ...vokerMessageProcessor_Instrumentation.java | 20 +++++++++++++ 6 files changed, 150 insertions(+) create mode 100644 instrumentation-security/mule-3.6/src/main/java/org/mule/construct/AbstractPipeline_Instrumentation.java create mode 100644 instrumentation-security/mule-3.6/src/main/java/org/mule/processor/InvokerMessageProcessor_Instrumentation.java create mode 100644 instrumentation-security/mule-3.7/src/main/java/org/mule/construct/AbstractPipeline_Instrumentation.java create mode 100644 instrumentation-security/mule-3.7/src/main/java/org/mule/processor/InvokerMessageProcessor_Instrumentation.java diff --git a/instrumentation-security/mule-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mule36/MuleHelper.java b/instrumentation-security/mule-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mule36/MuleHelper.java index 3754b8e9e..c7b8e71b4 100644 --- a/instrumentation-security/mule-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mule36/MuleHelper.java +++ b/instrumentation-security/mule-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mule36/MuleHelper.java @@ -3,11 +3,18 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; +import org.mule.api.processor.MessageProcessor; import org.mule.module.http.api.HttpHeaders; +import org.mule.module.http.api.listener.HttpListener; import org.mule.module.http.internal.domain.request.HttpRequest; +import org.mule.processor.InvokerMessageProcessor; +import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.mule.module.http.api.HttpHeaders.Names.X_FORWARDED_FOR; @@ -20,6 +27,7 @@ public class MuleHelper { public static final String HANDLE_REQUEST_METHOD = "handleRequest"; private static final String EMPTY = ""; public static final String LIBRARY_NAME = "MULE-SERVER"; + private static final Map handlerMap = new HashMap<>(); public static void processHttpRequestHeader(HttpRequest httpRequest, com.newrelic.api.agent.security.schema.HttpRequest securityRequest @@ -88,4 +96,24 @@ public static String getNrSecCustomAttribName(int hashcode) { return MULE_LOCK_CUSTOM_ATTRIB_NAME + Thread.currentThread().getId() + hashcode; } + public static void gatherURLMappings(HttpListener messageSource, List messageProcessors) { + try { + String path = messageSource.getPath(); + String handlerClass = null; + for (MessageProcessor processor: messageProcessors){ + if (processor instanceof InvokerMessageProcessor) { + handlerClass = getHandlerMap().remove(processor.hashCode()); + } + } + for (String method : messageSource.getAllowedMethods()){ + if (handlerClass != null){ + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(method, path, handlerClass)); + } + } + }catch (Exception ignored){} + } + + public static Map getHandlerMap() { + return handlerMap; + } } diff --git a/instrumentation-security/mule-3.6/src/main/java/org/mule/construct/AbstractPipeline_Instrumentation.java b/instrumentation-security/mule-3.6/src/main/java/org/mule/construct/AbstractPipeline_Instrumentation.java new file mode 100644 index 000000000..34415ac26 --- /dev/null +++ b/instrumentation-security/mule-3.6/src/main/java/org/mule/construct/AbstractPipeline_Instrumentation.java @@ -0,0 +1,27 @@ +package org.mule.construct; + +import com.newrelic.agent.security.instrumentation.mule36.MuleHelper; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import org.mule.api.processor.MessageProcessor; +import org.mule.api.source.MessageSource; +import org.mule.module.http.api.listener.HttpListener; + +import java.util.List; + +@Weave(type = MatchType.BaseClass, originalName = "org.mule.construct.AbstractPipeline") +public abstract class AbstractPipeline_Instrumentation { + + public abstract List getMessageProcessors(); + public abstract MessageSource getMessageSource(); + protected void doInitialise(){ + try { + Weaver.callOriginal(); + } finally { + if (getMessageSource() instanceof HttpListener){ + MuleHelper.gatherURLMappings((HttpListener) getMessageSource(), getMessageProcessors()); + } + } + } +} diff --git a/instrumentation-security/mule-3.6/src/main/java/org/mule/processor/InvokerMessageProcessor_Instrumentation.java b/instrumentation-security/mule-3.6/src/main/java/org/mule/processor/InvokerMessageProcessor_Instrumentation.java new file mode 100644 index 000000000..3e2871407 --- /dev/null +++ b/instrumentation-security/mule-3.6/src/main/java/org/mule/processor/InvokerMessageProcessor_Instrumentation.java @@ -0,0 +1,20 @@ +package org.mule.processor; + +import com.newrelic.agent.security.instrumentation.mule36.MuleHelper; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import org.mule.api.lifecycle.InitialisationException; + +@Weave(originalName = "org.mule.processor.InvokerMessageProcessor", type = MatchType.ExactClass) +public class InvokerMessageProcessor_Instrumentation { + protected Object object = Weaver.callOriginal(); + + public void initialise() throws InitialisationException { + try { + Weaver.callOriginal(); + } finally { + MuleHelper.getHandlerMap().put(hashCode(), object.getClass().getName()); + } + } +} diff --git a/instrumentation-security/mule-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mule37/MuleHelper.java b/instrumentation-security/mule-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mule37/MuleHelper.java index f05979db0..436cb6986 100644 --- a/instrumentation-security/mule-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mule37/MuleHelper.java +++ b/instrumentation-security/mule-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mule37/MuleHelper.java @@ -3,11 +3,18 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; +import org.mule.api.processor.MessageProcessor; import org.mule.module.http.api.HttpHeaders; +import org.mule.module.http.api.listener.HttpListener; import org.mule.module.http.internal.domain.request.HttpRequest; +import org.mule.processor.InvokerMessageProcessor; +import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.mule.module.http.api.HttpHeaders.Names.X_FORWARDED_FOR; @@ -19,6 +26,7 @@ public class MuleHelper { public static final String HANDLE_REQUEST_METHOD = "handleRequest"; private static final String EMPTY = ""; public static final String LIBRARY_NAME = "MULE-SERVER"; + private static final Map handlerMap = new HashMap<>(); public static void processHttpRequestHeader(HttpRequest httpRequest, com.newrelic.api.agent.security.schema.HttpRequest securityRequest) { for (String headerName : httpRequest.getHeaderNames()) { @@ -82,4 +90,24 @@ public static String getNrSecCustomAttribName(int hashcode) { return MULE_LOCK_CUSTOM_ATTRIB_NAME + Thread.currentThread().getId() + hashcode; } + public static void gatherURLMappings(HttpListener messageSource, List messageProcessors) { + try { + String path = messageSource.getPath(); + String handlerClass = null; + for (MessageProcessor processor: messageProcessors){ + if (processor instanceof InvokerMessageProcessor) { + handlerClass = getHandlerMap().remove(processor.hashCode()); + } + } + for (String method : messageSource.getAllowedMethods()){ + if (handlerClass != null){ + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(method, path, handlerClass)); + } + } + } catch (Exception ignored){} + } + + public static Map getHandlerMap() { + return handlerMap; + } } diff --git a/instrumentation-security/mule-3.7/src/main/java/org/mule/construct/AbstractPipeline_Instrumentation.java b/instrumentation-security/mule-3.7/src/main/java/org/mule/construct/AbstractPipeline_Instrumentation.java new file mode 100644 index 000000000..4952d39c0 --- /dev/null +++ b/instrumentation-security/mule-3.7/src/main/java/org/mule/construct/AbstractPipeline_Instrumentation.java @@ -0,0 +1,27 @@ +package org.mule.construct; + +import com.newrelic.agent.security.instrumentation.mule37.MuleHelper; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import org.mule.api.processor.MessageProcessor; +import org.mule.api.source.MessageSource; +import org.mule.module.http.api.listener.HttpListener; + +import java.util.List; + +@Weave(type = MatchType.BaseClass, originalName = "org.mule.construct.AbstractPipeline") +public abstract class AbstractPipeline_Instrumentation { + + public abstract List getMessageProcessors(); + public abstract MessageSource getMessageSource(); + protected void doInitialise(){ + try { + Weaver.callOriginal(); + } finally { + if (getMessageSource() instanceof HttpListener){ + MuleHelper.gatherURLMappings((HttpListener) getMessageSource(), getMessageProcessors()); + } + } + } +} diff --git a/instrumentation-security/mule-3.7/src/main/java/org/mule/processor/InvokerMessageProcessor_Instrumentation.java b/instrumentation-security/mule-3.7/src/main/java/org/mule/processor/InvokerMessageProcessor_Instrumentation.java new file mode 100644 index 000000000..94c152174 --- /dev/null +++ b/instrumentation-security/mule-3.7/src/main/java/org/mule/processor/InvokerMessageProcessor_Instrumentation.java @@ -0,0 +1,20 @@ +package org.mule.processor; + +import com.newrelic.agent.security.instrumentation.mule37.MuleHelper; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import org.mule.api.lifecycle.InitialisationException; + +@Weave(originalName = "org.mule.processor.InvokerMessageProcessor", type = MatchType.ExactClass) +public class InvokerMessageProcessor_Instrumentation { + protected Object object = Weaver.callOriginal(); + + public void initialise() throws InitialisationException { + try { + Weaver.callOriginal(); + } finally { + MuleHelper.getHandlerMap().put(hashCode(), object.getClass().getName()); + } + } +} From 9295b95dd4777cbd2a1d83ea59875e2be4b36877 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 28 Feb 2024 15:57:25 +0530 Subject: [PATCH 040/124] add config security.is_home_app --- .../com/newrelic/agent/security/util/IUtilConstants.java | 2 ++ .../src/main/java/com/newrelic/api/agent/security/Agent.java | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/util/IUtilConstants.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/util/IUtilConstants.java index 79946c855..8764c0b62 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/util/IUtilConstants.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/util/IUtilConstants.java @@ -22,6 +22,8 @@ public interface IUtilConstants { String NR_SECURITY_ENABLED = "security.enabled"; + String NR_SECURITY_HOME_APP = "security.is_home_app"; + String NR_SECURITY_CA_BUNDLE_PATH = "security.ca_bundle_path"; String NR_CSEC_DEBUG_LOGFILE_SIZE = "NR_CSEC_DEBUG_LOGFILE_SIZE"; String NR_CSEC_DEBUG_LOGFILE_MAX_COUNT = "NR_CSEC_DEBUG_LOGFILE_MAX_COUNT"; diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index 3e4fac1cf..ab0cf33d2 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -127,6 +127,9 @@ private void initialise() { this.getClass().getName()); logger.logInit(LogLevel.INFO, NewRelic.getAgent().getConfig().getValue(LowSeverityHelper.LOW_SEVERITY_HOOKS_ENABLED, LowSeverityHelper.DEFAULT)? "Low priority instrumentations are enabled.":"Low priority instrumentations are disabled!", this.getClass().getName()); + if( NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_HOME_APP, false) ) { + logger.logInit(LogLevel.INFO, "App being scanned is a Newrelic's Home Grown application", this.getClass().getName()); + } info.setIdentifier(ApplicationInfoUtils.envDetection()); ApplicationInfoUtils.continueIdentifierProcessing(info.getIdentifier(), config.getConfig()); info.generateAppInfo(config.getConfig()); @@ -281,7 +284,7 @@ public void registerOperation(AbstractOperation operation) { new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_RESPONSE_DATA, List.class)))); } - if(checkIfNRGeneratedEvent(operation)) { + if(!NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_HOME_APP, false) && checkIfNRGeneratedEvent(operation)) { logger.log(LogLevel.FINEST, DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL + JsonConverter.toJSON(operation), Agent.class.getName()); From 5eb59de1f2fedfb87714568f531cde0006e2fcb2 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 28 Feb 2024 16:54:14 +0530 Subject: [PATCH 041/124] Fix for issue NR-233188 --- .../instrumentation/apache/tomcat10/HttpServletHelper.java | 3 +-- .../instrumentation/apache/tomcat7/HttpServletHelper.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java b/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java index 89137ecb2..f118eb628 100644 --- a/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java +++ b/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java @@ -13,7 +13,6 @@ public class HttpServletHelper { private static final String EMPTY = ""; private static final String WILDCARD = "*"; - private static final String NULL = "null"; private static final String SEPARATOR = "/"; public static final String APACHE_TOMCAT_10 = "APACHE-TOMCAT-10"; @@ -43,7 +42,7 @@ private static void getJSPMappings(ServletContext servletContext, String dir) { getJSPMappings(servletContext, path); } else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, (path.startsWith(SEPARATOR) ? EMPTY : SEPARATOR) + path, NULL)); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, (path.startsWith(SEPARATOR) ? EMPTY : SEPARATOR) + path)); } } } diff --git a/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java b/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java index 7bbc8ff60..0822e64df 100644 --- a/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java +++ b/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java @@ -13,7 +13,6 @@ public class HttpServletHelper { private static final String EMPTY = ""; private static final String WILDCARD = "*"; - private static final String NULL = "null"; private static final String SEPARATOR = "/"; public static final String APACHE_TOMCAT_7 = "APACHE-TOMCAT-7"; @@ -43,7 +42,7 @@ private static void getJSPMappings(ServletContext servletContext, String dir) { getJSPMappings(servletContext, path); } else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, (path.startsWith(SEPARATOR) ? EMPTY : SEPARATOR) + path, NULL)); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, (path.startsWith(SEPARATOR) ? EMPTY : SEPARATOR) + path)); } } } From e2daaddf0107f218df699e229f28fd6cd32e7512 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 28 Feb 2024 16:54:52 +0530 Subject: [PATCH 042/124] Disabled jersey tests --- .../javax/ws/rs/api/test/SubresourceTest.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java index 384ef769d..874b7f0eb 100644 --- a/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java +++ b/instrumentation-security/jersey/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java @@ -6,25 +6,22 @@ import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.IdSubResource; import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; -import com.newrelic.agent.security.introspec.SecurityIntrospector; -import com.newrelic.api.agent.security.schema.AgentMetaData; import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.OrdersSubResource; import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.TestMapping; -import org.glassfish.jersey.client.HttpUrlConnectorProvider; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.test.JerseyTest; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; -import javax.ws.rs.client.Entity; import javax.ws.rs.core.Application; -import javax.ws.rs.core.Response; import java.util.Iterator; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "com.nr.instrumentation.security.jersey", "org.glassfish.jersey.server.internal" }) +@Ignore public class SubresourceTest extends JerseyTest { @BeforeClass public static void bringUp() { From 0a6179f44bb1de6f9055d7a3a39ce43e8615fcb4 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 28 Feb 2024 16:55:35 +0530 Subject: [PATCH 043/124] updated UTs for apache-tomcat --- .../security/instrumentation/tomcat10/APIEndpointTest.java | 3 +-- .../security/instrumentation/tomcat7/APIEndpointTest.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java index 249b1eea7..73c5b14d6 100644 --- a/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java +++ b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java @@ -31,7 +31,7 @@ public class APIEndpointTest { @Before public void setupEndpoints() { expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); - expectedMappings.put("/index.jsp", "null"); + expectedMappings.put("/index.jsp", null); expectedMappings.put("/*.jsp", "org.apache.jasper.servlet.JspServlet"); expectedMappings.put("/", DefaultServlet.class.getName()); expectedMappings.put("/*.jspx", "org.apache.jasper.servlet.JspServlet"); @@ -57,7 +57,6 @@ private void assertMappings(ApplicationURLMapping actualMapping) { String handler = expectedMappings.get(path); Assert.assertNotNull(actualMapping.getMethod()); - Assert.assertNotNull(actualMapping.getHandler()); Assert.assertEquals(handler, actualMapping.getHandler()); Assert.assertEquals("*", actualMapping.getMethod()); diff --git a/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java index b5ca8f3a2..e382baadf 100644 --- a/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java +++ b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java @@ -31,7 +31,7 @@ public class APIEndpointTest { @Before public void setupEndpoints() { expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); - expectedMappings.put("/index.jsp", "null"); + expectedMappings.put("/index.jsp", null); expectedMappings.put("/*.jsp", "org.apache.jasper.servlet.JspServlet"); expectedMappings.put("/", DefaultServlet.class.getName()); expectedMappings.put("/*.jspx", "org.apache.jasper.servlet.JspServlet"); @@ -57,7 +57,6 @@ private void assertMappings(ApplicationURLMapping actualMapping) { String handler = expectedMappings.get(path); Assert.assertNotNull(actualMapping.getMethod()); - Assert.assertNotNull(actualMapping.getHandler()); Assert.assertEquals(handler, actualMapping.getHandler()); Assert.assertEquals("*", actualMapping.getMethod()); From 4070ca855950e98c1d27ad21b7d713811277abd5 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 1 Mar 2024 10:05:23 +0530 Subject: [PATCH 044/124] NR-223811 Extract server port from websphere applications --- .../websphere-8/build.gradle | 30 +++++++++ .../websphere-8/lib/.gitignore | 2 + .../component/WebContainerImpl.java | 66 +++++++++++++++++++ settings.gradle | 2 + 4 files changed, 100 insertions(+) create mode 100644 instrumentation-security/websphere-8/build.gradle create mode 100644 instrumentation-security/websphere-8/lib/.gitignore create mode 100644 instrumentation-security/websphere-8/src/main/java/com/ibm/ws/webcontainer/component/WebContainerImpl.java diff --git a/instrumentation-security/websphere-8/build.gradle b/instrumentation-security/websphere-8/build.gradle new file mode 100644 index 000000000..0250668d8 --- /dev/null +++ b/instrumentation-security/websphere-8/build.gradle @@ -0,0 +1,30 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("javax.servlet:javax.servlet-api:3.0.1") + implementation(fileTree(include: ["*.jar"], dir: "lib")) +} + +def shouldBuild = fileTree(include: ["*.jar"], dir: "lib").size() > 0 + +compileJava { + enabled(shouldBuild) +} + +compileTestJava { + enabled(shouldBuild) +} + +tasks.getByName("writeCachedWeaveAttributes").enabled(shouldBuild) + +jar { + enabled(shouldBuild) + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.websphere-8' } +} + +site { + title 'WebSphere' + type 'Appserver' + versionOverride '[8,9)' +} \ No newline at end of file diff --git a/instrumentation-security/websphere-8/lib/.gitignore b/instrumentation-security/websphere-8/lib/.gitignore new file mode 100644 index 000000000..c96a04f00 --- /dev/null +++ b/instrumentation-security/websphere-8/lib/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/instrumentation-security/websphere-8/src/main/java/com/ibm/ws/webcontainer/component/WebContainerImpl.java b/instrumentation-security/websphere-8/src/main/java/com/ibm/ws/webcontainer/component/WebContainerImpl.java new file mode 100644 index 000000000..2b28914d4 --- /dev/null +++ b/instrumentation-security/websphere-8/src/main/java/com/ibm/ws/webcontainer/component/WebContainerImpl.java @@ -0,0 +1,66 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package com.ibm.ws.webcontainer.component; + +import java.text.MessageFormat; +import java.util.logging.Level; + +import javax.management.ObjectName; + +import com.ibm.websphere.management.Session; +import com.ibm.websphere.management.configservice.ConfigService; +import com.ibm.websphere.management.configservice.ConfigServiceFactory; +import com.ibm.websphere.management.configservice.ConfigServiceHelper; +import com.ibm.websphere.product.WASDirectory; +import com.ibm.websphere.product.WASProductInfo; +import com.ibm.websphere.runtime.ServerName; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.utils.logging.LogLevel; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +@Weave +public class WebContainerImpl { + + public void start() { +// String instanceName = ServerName.getFullName(); +// if (instanceName != null) { +// AgentBridge.publicApi.setInstanceName(instanceName); +// } + Integer port = getServerPort(); + if (port != null) { + //TODO find protocol + NewRelicSecurity.getAgent().setApplicationConnectionConfig(port, "http"); +// AgentBridge.publicApi.setAppServerPort(port); + } + Weaver.callOriginal(); + } + + private Integer getServerPort() { + try { + ConfigService cs = ConfigServiceFactory.getConfigService(); + Session session = new Session(); + ObjectName[] serverIndexONs = cs.resolve(session, "ServerIndex="); + ObjectName[] namedEndPointsONs = cs.queryConfigObjects(session, serverIndexONs[0], + ConfigServiceHelper.createObjectName(null, "NamedEndPoint"), null); + for (ObjectName namedEndPointsON : namedEndPointsONs) { + String endPointName = (String) cs.getAttribute(session, namedEndPointsON, "endPointName"); + if (endPointName.equals("WC_defaulthost")) { + Integer port = (Integer) cs.getAttribute(session, (cs.queryConfigObjects(session, namedEndPointsON, + ConfigServiceHelper.createObjectName(null, "EndPoint"), null)[0]), "port"); + return port; + } + } + } catch (Exception ex) { + NewRelicSecurity.getAgent().log(LogLevel.FINER, "Exception getting port", ex, this.getClass().getName()); +// AgentBridge.getAgent().getLogger().log(Level.FINER, ex, "Exception getting port"); + } + return null; + } + +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 7a020a5ce..932c95716 100644 --- a/settings.gradle +++ b/settings.gradle @@ -178,3 +178,5 @@ include 'instrumentation:spymemcached-2.12.0' include 'instrumentation:jetty-12' include 'instrumentation:mule-3.7' include 'instrumentation:mule-3.6' + +include 'instrumentation:websphere-8' From e0c2d59caef8a4595c0fc6da9a0c3ff885f391aa Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Fri, 1 Mar 2024 10:05:42 +0530 Subject: [PATCH 045/124] Fix: API Endpoint Support Servlet 3 (#197) * Separated Endpoint Support for Servlet, as previous support is not applied to versions < 3.0 * Unit tests for Servlet API Endpoint Support --- .../servlet-3.0/build.gradle | 24 +++++ .../servlet30/HttpServletHelper.java | 52 +++++++++++ ...tContainerInitializer_Instrumentation.java | 3 +- .../servlet30/ApiEndpointTest.java} | 9 +- .../servlet30/HttpServletServer.java | 91 +++++++++++++++++++ settings.gradle | 1 + 6 files changed, 174 insertions(+), 6 deletions(-) create mode 100644 instrumentation-security/servlet-3.0/build.gradle create mode 100644 instrumentation-security/servlet-3.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet30/HttpServletHelper.java rename instrumentation-security/{servlet-2.4 => servlet-3.0}/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java (89%) rename instrumentation-security/{servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletContainerInitializerTest.java => servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java} (83%) create mode 100644 instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java diff --git a/instrumentation-security/servlet-3.0/build.gradle b/instrumentation-security/servlet-3.0/build.gradle new file mode 100644 index 000000000..1f955ae64 --- /dev/null +++ b/instrumentation-security/servlet-3.0/build.gradle @@ -0,0 +1,24 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation('jakarta.servlet:jakarta.servlet-api:4.0.4') + + testImplementation('org.apache.tomcat.embed:tomcat-embed-core:9.0.70') +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.servlet-3.0' } +} + +verifyInstrumentation { + passesOnly 'jakarta.servlet:jakarta.servlet-api:[4.0.2,5.0.0-M1)' + passesOnly 'javax.servlet:javax.servlet-api:[0,)' + fails 'javax.servlet:servlet-api:[2.4,)' + exclude 'javax.servlet:servlet-api:2.4.public_draft' +} + +site { + title 'Servlet' + type 'Framework' +} diff --git a/instrumentation-security/servlet-3.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet30/HttpServletHelper.java b/instrumentation-security/servlet-3.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet30/HttpServletHelper.java new file mode 100644 index 000000000..805811544 --- /dev/null +++ b/instrumentation-security/servlet-3.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet30/HttpServletHelper.java @@ -0,0 +1,52 @@ +package com.newrelic.agent.security.instrumentation.servlet30; + + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.api.agent.security.utils.logging.LogLevel; + +import javax.servlet.ServletContext; +import javax.servlet.ServletRegistration; +import java.util.Collection; +import java.util.Map; + +public class HttpServletHelper { + private static final String WILDCARD = "*"; + private static final String SEPARATOR = "/"; + public static final String SERVLET_3_0 = "SERVLET-3.0"; + public static void gatherURLMappings(ServletContext servletContext) { + try { + Map servletRegistrations = servletContext.getServletRegistrations(); + getJSPMappings(servletContext, SEPARATOR); + + for (ServletRegistration servletRegistration : servletRegistrations.values()) { + for (String s : servletRegistration.getMappings()) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, s, servletRegistration.getClassName())); + } + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, SERVLET_3_0, e.getMessage()), e, HttpServletHelper.class.getName()); + } + } + + public static void getJSPMappings(ServletContext servletContext, String dir) { + try { + if(dir.endsWith(SEPARATOR)){ + Collection resourcePaths = servletContext.getResourcePaths(dir); + for (String path : resourcePaths) { + if(path.endsWith(SEPARATOR)) { + getJSPMappings(servletContext, path); + } + else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); + } + } + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, SERVLET_3_0, e.getMessage()), e, HttpServletHelper.class.getName()); + } + } +} diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java b/instrumentation-security/servlet-3.0/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java similarity index 89% rename from instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java rename to instrumentation-security/servlet-3.0/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java index 9a46ec883..5956afcad 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java +++ b/instrumentation-security/servlet-3.0/src/main/java/javax/servlet/ServletContainerInitializer_Instrumentation.java @@ -3,8 +3,7 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.newrelic.agent.security.instrumentation.servlet24.HttpServletHelper; - +import com.newrelic.agent.security.instrumentation.servlet30.HttpServletHelper; import java.util.Set; @Weave(type = MatchType.Interface, originalName = "javax.servlet.ServletContainerInitializer") diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletContainerInitializerTest.java b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java similarity index 83% rename from instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletContainerInitializerTest.java rename to instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java index 797cd5150..9da366969 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletContainerInitializerTest.java +++ b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java @@ -1,9 +1,10 @@ -package com.nr.agent.security.instrumentation.servlet24; +package com.nr.agent.security.instrumentation.servlet30; import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import org.apache.catalina.servlets.DefaultServlet; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; @@ -12,14 +13,14 @@ import java.util.Iterator; @RunWith(SecurityInstrumentationTestRunner.class) -@InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) -public class ServletContainerInitializerTest { +@InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet30" }) +public class ApiEndpointTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); @Test public void testURLMappings() { - String handler = "com.nr.agent.security.instrumentation.servlet24.HttpTestServlet"; + String handler = DefaultServlet.class.getName(); String method = "*"; Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); diff --git a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java new file mode 100644 index 000000000..de666f5f6 --- /dev/null +++ b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java @@ -0,0 +1,91 @@ +package com.nr.agent.security.instrumentation.servlet30; + +import org.apache.catalina.Context; +import org.apache.catalina.LifecycleState; +import org.apache.catalina.connector.Connector; +import org.apache.catalina.servlets.DefaultServlet; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory; +import org.apache.tomcat.util.http.fileupload.FileUtils; +import org.junit.rules.ExternalResource; + +import javax.servlet.ServletContainerInitializer; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import java.io.File; +import java.io.IOException; +import java.net.ServerSocket; +import java.util.Collections; +import java.util.Set; + +@WebServlet("/*") +public class HttpServletServer extends ExternalResource { + + private final int port; + private Tomcat server; + private File tmp; + public HttpServletServer() { + this.port = getRandomPort(); + } + + @Override + protected void before() throws Throwable { + startServer(); + } + + @Override + protected void after() { + stop(); + } + + private static int getRandomPort() { + try (ServerSocket socket = new ServerSocket(0);){ + return socket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Unable to allocate ephemeral port "); + } + } + + private void startServer () throws Exception { + TomcatURLStreamHandlerFactory.disable(); + + server = new Tomcat(); + server.setPort(port); + + tmp = new File("./tmp"); + server.setBaseDir(tmp.getAbsolutePath()); + + Context context = server.addContext("", tmp.getAbsolutePath()); + context.addServletContainerInitializer(new ServletContainerInitializer() { + @Override + public void onStartup(Set> c, ServletContext ctx){ + System.out.println("testing..."); + } + }, Collections.emptySet()); + + Tomcat.addServlet(context, "servlet", new DefaultServlet()); + context.addServletMappingDecoded("/*","servlet"); + context.addServletMappingDecoded("/test","servlet"); + + final Connector connector = new Connector(); + connector.setPort(port); + server.getService().addConnector(connector); + + server.start(); + } + + private void stop() { + if (server.getServer() != null && server.getServer().getState() != LifecycleState.DESTROYED) { + try { + if (server.getServer().getState() != LifecycleState.STOPPED) { + server.stop(); + } + server.destroy(); + FileUtils.forceDelete(tmp); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 778e17794..f494a7d70 100644 --- a/settings.gradle +++ b/settings.gradle @@ -184,3 +184,4 @@ include 'instrumentation:spymemcached-2.12.0' include 'instrumentation:jetty-12' include 'instrumentation:mule-3.7' include 'instrumentation:mule-3.6' +include 'instrumentation:servlet-3.0' From f62c901d56b70dc137d0dab4327f9d1152cbdab5 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 1 Mar 2024 17:39:49 +0530 Subject: [PATCH 046/124] updated packaging for play --- instrumentation-security/play-2.13_2.7/build.gradle | 2 +- instrumentation-security/play-2.4/build.gradle | 2 +- instrumentation-security/play-2.6/build.gradle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/instrumentation-security/play-2.13_2.7/build.gradle b/instrumentation-security/play-2.13_2.7/build.gradle index 0fa5fde0a..23b3cf874 100644 --- a/instrumentation-security/play-2.13_2.7/build.gradle +++ b/instrumentation-security/play-2.13_2.7/build.gradle @@ -37,7 +37,7 @@ dependencies { } jar { - manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.play-2.13_2.7' } + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.play-2.13_2.7' } } verifyInstrumentation { diff --git a/instrumentation-security/play-2.4/build.gradle b/instrumentation-security/play-2.4/build.gradle index 7360567ab..2c3810bba 100644 --- a/instrumentation-security/play-2.4/build.gradle +++ b/instrumentation-security/play-2.4/build.gradle @@ -11,7 +11,7 @@ dependencies { } jar { - manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.play-2.4' } + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.play-2.4' } } verifyInstrumentation { diff --git a/instrumentation-security/play-2.6/build.gradle b/instrumentation-security/play-2.6/build.gradle index c0bf094d1..b3fecafda 100644 --- a/instrumentation-security/play-2.6/build.gradle +++ b/instrumentation-security/play-2.6/build.gradle @@ -34,7 +34,7 @@ dependencies { } jar { - manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.play-2.6' } + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.play-2.6' } } verifyInstrumentation { From c5af8498f9fcd1cca0e540b0ce9be56577e41720 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 4 Mar 2024 10:40:58 +0530 Subject: [PATCH 047/124] Enable netty instrumentation --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 7a020a5ce..86ddb310e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -118,7 +118,7 @@ include 'instrumentation:akka-http-core-10.0' include 'instrumentation:akka-http-2.11_10.0.0' include 'instrumentation:jetty-9' include 'instrumentation:jetty-11' -//include 'instrumentation:netty-4.0.0' +include 'instrumentation:netty-4.0.0' //include 'instrumentation:grpc-1.40.0' include 'instrumentation:dynamodb-1.11.80' include 'instrumentation:dynamodb-1.11.390' From 724bc73712855feee2a3e7e40ffd622b412dc34a Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 4 Mar 2024 10:43:26 +0530 Subject: [PATCH 048/124] NR-234865 : Fix misleading operational lock for request and response Co-authored-by: Lovesh Baya --- ...ChannelInboundHandler_Instrumentation.java | 4 ++-- ...hannelOutboundHandler_Instrumentation.java | 4 ++-- .../io/netty400/utils/NettyUtils.java | 22 ++++++++++--------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java index 4fa642234..36531082f 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java @@ -19,7 +19,7 @@ public abstract class ChannelInboundHandler_Instrumentation { public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - boolean isLockAcquired = NettyUtils.acquireNettyLockIfPossible(); + boolean isLockAcquired = NettyUtils.acquireNettyLockIfPossible(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK); if (isLockAcquired) { NettyUtils.processSecurityRequest(ctx, msg, getClass().getName()); if (!StringUtils.startsWith(getClass().getName(), NettyUtils.IO_NETTY)) { @@ -30,7 +30,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception Weaver.callOriginal(); } finally { if (isLockAcquired) { - NettyUtils.releaseNettyLock(); + NettyUtils.releaseNettyLock(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK); } } } diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java index 5990decd6..8daeaa63c 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java @@ -18,7 +18,7 @@ public abstract class ChannelOutboundHandler_Instrumentation { public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - boolean isLockAcquired = NettyUtils.acquireNettyLockIfPossible(); + boolean isLockAcquired = NettyUtils.acquireNettyLockIfPossible(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND); if (isLockAcquired) { NettyUtils.processSecurityResponse(ctx, msg); NettyUtils.sendRXSSEvent(ctx, msg, getClass().getName(), NettyUtils.WRITE_METHOD_NAME); @@ -27,7 +27,7 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) Weaver.callOriginal(); } finally { if (isLockAcquired) { - NettyUtils.releaseNettyLock(); + NettyUtils.releaseNettyLock(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND); } } } diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java index 40428c49c..32223dcfa 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java @@ -15,6 +15,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; @@ -26,7 +27,8 @@ public class NettyUtils { public static String NR_SEC_CUSTOM_ATTRIB_NAME = "NETTY-4.8-REQ-BODY-TRACKER"; - public static String NR_SEC_NETTY_OPERATIONAL_LOCK = "NR_SEC_NETTY_OPERATIONAL_LOCK"; + public static String NR_SEC_NETTY_OPERATIONAL_LOCK = "NR_SEC_NETTY_OPERATIONAL_LOCK_INBOUND"; + public static String NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND = "NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND"; private static final String X_FORWARDED_FOR = "x-forwarded-for"; private static final String EMPTY = ""; public static final String WRITE_METHOD_NAME = "write"; @@ -57,7 +59,7 @@ public static void processSecurityRequest(ChannelHandlerContext ctx, Object msg, securityMetaData.setTracingHeaderValue(getTraceHeader(securityRequest.getHeaders())); securityRequest.setProtocol(((HttpRequest) msg).getProtocolVersion().protocolName()); - securityRequest.setContentType(securityRequest.getHeaders().get("content-type")); + securityRequest.setContentType(securityRequest.getHeaders().get(HttpHeaders.Names.CONTENT_TYPE)); StackTraceElement[] stack = Thread.currentThread().getStackTrace(); securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(stack, 2, stack.length)); securityRequest.setRequestParsed(true); @@ -178,7 +180,7 @@ public static void processSecurityResponse(ChannelHandlerContext ctx, Object msg com.newrelic.api.agent.security.schema.HttpResponse securityResponse = securityMetaData.getResponse(); processResponseHeaders((HttpResponse) msg, securityResponse); - securityResponse.setResponseContentType(((FullHttpResponse) msg).headers().get("content-type")); + securityResponse.setResponseContentType(((FullHttpResponse) msg).headers().get(HttpHeaders.Names.CONTENT_TYPE)); securityResponse.getResponseBody().append(((FullHttpResponse) msg).content().toString(StandardCharsets.UTF_8)); } } catch (Throwable e) { @@ -217,29 +219,29 @@ private static void processResponseHeaders(HttpResponse response, com.newrelic.a } } - public static boolean isNettyLockAcquired() { + public static boolean isNettyLockAcquired(String operationLock) { try { return NewRelicSecurity.isHookProcessingActive() && - Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(getNrSecOperationalLockName(), Boolean.class)); + Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(operationLock + Thread.currentThread().getId(), Boolean.class)); } catch (Throwable ignored) {} return false; } - public static boolean acquireNettyLockIfPossible() { + public static boolean acquireNettyLockIfPossible(String operationLock) { try { if (NewRelicSecurity.isHookProcessingActive() && - !isNettyLockAcquired()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecOperationalLockName(), true); + !isNettyLockAcquired(operationLock)) { + NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(operationLock + Thread.currentThread().getId(), true); return true; } } catch (Throwable ignored){} return false; } - public static void releaseNettyLock() { + public static void releaseNettyLock(String operationLock) { try { if(NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecOperationalLockName(), null); + NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(operationLock + Thread.currentThread().getId(), null); } } catch (Throwable ignored){} } From 8f83af52b5f39915477c599ae1211fd066472764 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 4 Mar 2024 10:53:03 +0530 Subject: [PATCH 049/124] NR-234868 : add instrumentation to SimpleChannelInboundHandler#channelRead0 for service trace registration --- ...eChannelInboundHandler_Instrumentation.java | 18 ++++++++++++++++++ .../instrumentation/helpers/ServletHelper.java | 1 + .../agent/security/schema/AgentMetaData.java | 4 ++++ 3 files changed, 23 insertions(+) create mode 100644 instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java new file mode 100644 index 000000000..fe999383c --- /dev/null +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java @@ -0,0 +1,18 @@ +package security.io.netty400.channel; + +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import io.netty.channel.ChannelHandlerContext; +import security.io.netty400.utils.NettyUtils; + +@Weave(type = MatchType.BaseClass, originalName = "io.netty.channel.SimpleChannelInboundHandler") +public class SimpleChannelInboundHandler_Instrumentation { + + protected void channelRead0(ChannelHandlerContext ctx, I msg) throws Exception { + if (!StringUtils.startsWith(getClass().getName(), NettyUtils.IO_NETTY)) { + ServletHelper.registerUserLevelCode(NettyUtils.IO_NETTY); + } + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java index df4fe1ee2..f3e8c08cf 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java @@ -155,6 +155,7 @@ public static boolean registerUserLevelCode(String frameworkName, boolean asyncC SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); if (!securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(frameworkName)) { securityMetaData.getMetaData().setUserLevelServiceMethodEncountered(true); + securityMetaData.getMetaData().setUserLevelServiceMethodEncounteredFramework(frameworkName); StackTraceElement[] trace = Thread.currentThread().getStackTrace(); securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(trace, asyncContext?2:3, trace.length)); return true; diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java index 751f4d24f..2a72ff804 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java @@ -163,6 +163,10 @@ public void setUserLevelServiceMethodEncountered(boolean userLevelServiceMethodE this.userLevelServiceMethodEncountered = userLevelServiceMethodEncountered; } + public void setUserLevelServiceMethodEncounteredFramework(String userLevelServiceMethodEncounteredFramework) { + this.userLevelServiceMethodEncounteredFramework = userLevelServiceMethodEncounteredFramework; + } + public AppServerInfo getAppServerInfo() { return appServerInfo; } From 56ff83c99f672a2744f2be926cdd5643112cc1d9 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 4 Mar 2024 12:11:59 +0530 Subject: [PATCH 050/124] NR-234868 : add call to original and fix content type setter --- .../SimpleChannelInboundHandler_Instrumentation.java | 9 +++++++-- .../main/java/security/io/netty400/utils/NettyUtils.java | 8 +++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java index fe999383c..b82cf5af4 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; import io.netty.channel.ChannelHandlerContext; import security.io.netty400.utils.NettyUtils; @@ -11,8 +12,12 @@ public class SimpleChannelInboundHandler_Instrumentation { protected void channelRead0(ChannelHandlerContext ctx, I msg) throws Exception { - if (!StringUtils.startsWith(getClass().getName(), NettyUtils.IO_NETTY)) { - ServletHelper.registerUserLevelCode(NettyUtils.IO_NETTY); + try { + if (!StringUtils.startsWith(getClass().getName(), NettyUtils.IO_NETTY)) { + ServletHelper.registerUserLevelCode(NettyUtils.IO_NETTY); + } + } catch (Exception e){ } + Weaver.callOriginal(); } } diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java index 32223dcfa..6ea0677bc 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java @@ -59,9 +59,11 @@ public static void processSecurityRequest(ChannelHandlerContext ctx, Object msg, securityMetaData.setTracingHeaderValue(getTraceHeader(securityRequest.getHeaders())); securityRequest.setProtocol(((HttpRequest) msg).getProtocolVersion().protocolName()); - securityRequest.setContentType(securityRequest.getHeaders().get(HttpHeaders.Names.CONTENT_TYPE)); - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(stack, 2, stack.length)); + securityRequest.setContentType(securityRequest.getHeaders().get("content-type")); + if (!securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(IO_NETTY)){ + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(stack, 2, stack.length)); + } securityRequest.setRequestParsed(true); } else if (msg instanceof HttpContent) { if (!(secMetaObj instanceof SecurityMetaData) || From cce8e62f6219a4ad34878ebd54dd49733854a54e Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 4 Mar 2024 14:02:23 +0530 Subject: [PATCH 051/124] Add critical logging to netty support Co-authored-by: Lovesh Baya --- .../io/netty400/utils/NettyUtils.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java index 6ea0677bc..439e3d1c6 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java @@ -12,6 +12,7 @@ import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpContent; @@ -26,6 +27,7 @@ import java.util.Set; public class NettyUtils { + public static final String NETTY_4_0_0 = "NETTY-4.0.0"; public static String NR_SEC_CUSTOM_ATTRIB_NAME = "NETTY-4.8-REQ-BODY-TRACKER"; public static String NR_SEC_NETTY_OPERATIONAL_LOCK = "NR_SEC_NETTY_OPERATIONAL_LOCK_INBOUND"; public static String NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND = "NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND"; @@ -34,6 +36,8 @@ public class NettyUtils { public static final String WRITE_METHOD_NAME = "write"; public static final String IO_NETTY = "io.netty."; + private static final String ERROR_GETTING_SERVER_PORT = "Instrumentation library: %s , error while getting server port %s"; + private static final String ERROR_PARSING_HTTP_RESPONSE_DATA = "Instrumentation library: %s , error while parsing HTTP response data : %s"; public static void processSecurityRequest(ChannelHandlerContext ctx, Object msg, String className) { try { @@ -84,7 +88,7 @@ public static void processSecurityRequest(ChannelHandlerContext ctx, Object msg, } } } catch (Throwable ignored) { - ignored.printStackTrace(); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_PARSING_HTTP_REQUEST_DATA, NETTY_4_0_0, ignored.getMessage()), ignored, NettyUtils.class.getName()); } } @@ -95,7 +99,9 @@ private static void setServerPortDetails(com.newrelic.api.agent.security.schema. return; } securityRequest.setServerPort(Integer.parseInt(port)); - } catch (Throwable throwable) {} + } catch (Throwable throwable) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(ERROR_GETTING_SERVER_PORT, NETTY_4_0_0, throwable.getMessage()), throwable, NettyUtils.class.getName()); + } } private static void setClientAddressDetails(SecurityMetaData securityMetaData, String address) { @@ -186,7 +192,7 @@ public static void processSecurityResponse(ChannelHandlerContext ctx, Object msg securityResponse.getResponseBody().append(((FullHttpResponse) msg).content().toString(StandardCharsets.UTF_8)); } } catch (Throwable e) { - e.printStackTrace(); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(ERROR_PARSING_HTTP_RESPONSE_DATA, NETTY_4_0_0, e.getMessage()), e, NettyUtils.class.getName()); } } @@ -207,9 +213,11 @@ public static void sendRXSSEvent(ChannelHandlerContext ctx, Object msg, String c ServletHelper.tmpFileCleanUp(NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getTempFiles()); } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { - e.printStackTrace(); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, NETTY_4_0_0, e.getMessage()), e, NettyUtils.class.getName()); throw e; } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, NETTY_4_0_0, e.getMessage()), e, NettyUtils.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, NETTY_4_0_0, e.getMessage()), e, NettyUtils.class.getName()); } } @@ -247,8 +255,4 @@ public static void releaseNettyLock(String operationLock) { } } catch (Throwable ignored){} } - - private static String getNrSecOperationalLockName() { - return NR_SEC_NETTY_OPERATIONAL_LOCK + Thread.currentThread().getId(); - } } From bb24c9e8810577926f3a704b336c71fd8fdf993d Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 4 Mar 2024 16:23:31 +0530 Subject: [PATCH 052/124] remove lamda function to fix class circularity error --- .../main/java/com/newrelic/api/agent/security/Agent.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index ab0cf33d2..0caab9e9d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -433,7 +433,11 @@ private static void processStackTrace(AbstractOperation operation) { private static void setAPIId(AbstractOperation operation, List traceForIdCalc, VulnerabilityCaseType vulnerabilityCaseType) { try { traceForIdCalc.add(operation.getSourceMethod().hashCode()); - operation.setApiID(vulnerabilityCaseType.getCaseType() + "-" + HashGenerator.getXxHash64Digest(traceForIdCalc.stream().mapToInt(Integer::intValue).toArray())); + int[] traceArray = new int[traceForIdCalc.size()]; + for (int i = 0; i < traceForIdCalc.size(); i++) { + traceArray[i] = traceForIdCalc.get(i); + } + operation.setApiID(vulnerabilityCaseType.getCaseType() + "-" + HashGenerator.getXxHash64Digest(traceArray)); } catch (IOException e) { operation.setApiID("UNDEFINED"); } From 4cfba3d6730744edcdd5f56c05268662be49d03f Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 4 Mar 2024 16:55:38 +0530 Subject: [PATCH 053/124] Drop CSEC generated events --- .../newrelic/api/agent/security/Agent.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index 0caab9e9d..9f1c35242 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -284,6 +284,13 @@ public void registerOperation(AbstractOperation operation) { new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_RESPONSE_DATA, List.class)))); } + if(NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_HOME_APP, false) && checkIfCSECGeneratedEvent(operation)) { + logger.log(LogLevel.FINEST, DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL + + JsonConverter.toJSON(operation), + Agent.class.getName()); + return; + } + if(!NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_HOME_APP, false) && checkIfNRGeneratedEvent(operation)) { logger.log(LogLevel.FINEST, DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL + JsonConverter.toJSON(operation), @@ -309,6 +316,18 @@ public void registerOperation(AbstractOperation operation) { } } + private boolean checkIfCSECGeneratedEvent(AbstractOperation operation) { + for (int i = 1, j = 0; i < operation.getStackTrace().length; i++) { + // Only remove consecutive top com.newrelic and com.nr. elements from stack. + if (i - 1 == j && StringUtils.startsWithAny(operation.getStackTrace()[i].getClassName(), "com.newrelic.agent.security.", "com.newrelic.api.agent.")) { + j++; + } else if (StringUtils.startsWithAny(operation.getStackTrace()[i].getClassName(), "com.newrelic.agent.security.", "com.newrelic.api.agent.")) { + return true; + } + } + return false; + } + private void logIfIastScanForFirstTime(K2RequestIdentifier fuzzRequestIdentifier, HttpRequest request) { String url = StringUtils.EMPTY; From 232c2ba6ff0d20cf09510ec5b2ee7d86b82c8b1c Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 4 Mar 2024 17:09:26 +0530 Subject: [PATCH 054/124] Fix for SSL Exception with missing port detection --- .../instrumentator/httpclient/RestClient.java | 31 +++++++------------ .../httpclient/RestRequestProcessor.java | 19 ++++++++++-- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java index f39be870c..83a67f613 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java @@ -121,28 +121,9 @@ public OkHttpClient getClient() { return clientThreadLocal.get(); } - public void fireRequest(FuzzRequestBean httpRequest, List endpoints, int repeatCount, String fuzzRequestId){ + public void fireRequest(FuzzRequestBean httpRequest, List endpoints, int repeatCount, String fuzzRequestId, boolean postSSL){ int responseCode = 999; - if(endpoints.isEmpty()){ - Request request = RequestUtils.generateK2Request(httpRequest, String.format(IAgentConstants.ENDPOINT_LOCALHOST_S, httpRequest.getProtocol(), httpRequest.getServerPort())); - if (request != null) { - try { - responseCode = RestClient.getInstance().fireRequest(request, repeatCount + endpoints.size() -1, fuzzRequestId); - } catch (SSLException e) { - logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, request), e, RestClient.class.getName()); - logger.postLogMessageIfNecessary(LogLevel.WARNING, - String.format(CALL_FAILED_REQUEST_S_REASON, fuzzRequestId), - e, RestRequestProcessor.class.getName()); - RestRequestThreadPool.getInstance().getProcessedIds().putIfAbsent(fuzzRequestId, new HashSet<>()); - // TODO: Add to fuzz fail count in HC and remove FuzzFailEvent if not needed. - FuzzFailEvent fuzzFailEvent = new FuzzFailEvent(AgentInfo.getInstance().getApplicationUUID()); - fuzzFailEvent.setFuzzHeader(request.header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID)); - EventSendPool.getInstance().sendEvent(fuzzFailEvent); - } - } - return; - } for (String endpoint : endpoints) { Request request = RequestUtils.generateK2Request(httpRequest, endpoint); try { @@ -153,6 +134,16 @@ public void fireRequest(FuzzRequestBean httpRequest, List endpoints, int break; } catch (SSLException e){ logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, request), e, RestClient.class.getName()); + if(postSSL){ + logger.postLogMessageIfNecessary(LogLevel.WARNING, + String.format(CALL_FAILED_REQUEST_S_REASON, fuzzRequestId), + e, RestRequestProcessor.class.getName()); + RestRequestThreadPool.getInstance().getProcessedIds().putIfAbsent(fuzzRequestId, new HashSet<>()); + // TODO: Add to fuzz fail count in HC and remove FuzzFailEvent if not needed. + FuzzFailEvent fuzzFailEvent = new FuzzFailEvent(AgentInfo.getInstance().getApplicationUUID()); + fuzzFailEvent.setFuzzHeader(request.header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID)); + EventSendPool.getInstance().sendEvent(fuzzFailEvent); + } } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java index 92c13e89b..7daaf44fb 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java @@ -38,6 +38,7 @@ public class RestRequestProcessor implements Callable { public static final String JSON_PARSING_ERROR_WHILE_PROCESSING_FUZZING_REQUEST_S = "JSON parsing error while processing fuzzing request : %s"; private static final int MAX_REPETITION = 3; + public static final String ENDPOINT_LOCALHOST_S = "%s://localhost:%s"; private IntCodeControlCommand controlCommand; private int repeatCount; @@ -103,8 +104,13 @@ public Boolean call() throws InterruptedException { MonitorGrpcFuzzFailRequestQueueThread.submitNewTask(); GrpcClientRequestReplayHelper.getInstance().addToRequestQueue(new ControlCommandDto(controlCommand.getId(), httpRequest, payloadList)); } else { + boolean postSSL = false; List endpoints = prepareAllEndpoints(NewRelicSecurity.getAgent().getApplicationConnectionConfig()); - RestClient.getInstance().fireRequest(httpRequest, endpoints, repeatCount + endpoints.size() -1, controlCommand.getId()); + if (endpoints.isEmpty()){ + endpoints = prepareAllEndpoints(httpRequest); + postSSL = true; + } + RestClient.getInstance().fireRequest(httpRequest, endpoints, repeatCount + endpoints.size() -1, controlCommand.getId(), postSSL); } return true; } catch (JsonProcessingException e){ @@ -127,11 +133,18 @@ public Boolean call() throws InterruptedException { return true; } + private List prepareAllEndpoints(FuzzRequestBean httpRequest) { + List endpoitns = new ArrayList<>(); + endpoitns.add(String.format(ENDPOINT_LOCALHOST_S, httpRequest.getProtocol(), httpRequest.getServerPort())); + endpoitns.add(String.format(ENDPOINT_LOCALHOST_S, toggleProtocol(httpRequest.getProtocol()), httpRequest.getServerPort())); + return endpoitns; + } + private List prepareAllEndpoints(Map applicationConnectionConfig) { List endpoitns = new ArrayList<>(); for (Map.Entry connectionConfig : applicationConnectionConfig.entrySet()) { - endpoitns.add(String.format("%s://localhost:%s", connectionConfig.getValue(), connectionConfig.getKey())); - endpoitns.add(String.format("%s://localhost:%s", toggleProtocol(connectionConfig.getValue()), connectionConfig.getKey())); + endpoitns.add(String.format(ENDPOINT_LOCALHOST_S, connectionConfig.getValue(), connectionConfig.getKey())); + endpoitns.add(String.format(ENDPOINT_LOCALHOST_S, toggleProtocol(connectionConfig.getValue()), connectionConfig.getKey())); } return endpoitns; } From 4738cb50c7ca7237d4ae57518b1efa92fc13f508 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 4 Mar 2024 18:31:19 +0530 Subject: [PATCH 055/124] Add checks to operational lock mechanism Co-authored-by: Lovesh Baya --- .../channel/ChannelInboundHandler_Instrumentation.java | 7 ++++++- .../channel/ChannelOutboundHandler_Instrumentation.java | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java index 36531082f..10c000dc3 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java @@ -13,13 +13,18 @@ import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpRequest; import security.io.netty400.utils.NettyUtils; @Weave(type = MatchType.Interface, originalName = "io.netty.channel.ChannelInboundHandler") public abstract class ChannelInboundHandler_Instrumentation { public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - boolean isLockAcquired = NettyUtils.acquireNettyLockIfPossible(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK); + boolean isLockAcquired = false; + if (msg instanceof HttpRequest || msg instanceof HttpContent){ + isLockAcquired = NettyUtils.acquireNettyLockIfPossible(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK); + } if (isLockAcquired) { NettyUtils.processSecurityRequest(ctx, msg, getClass().getName()); if (!StringUtils.startsWith(getClass().getName(), NettyUtils.IO_NETTY)) { diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java index 8daeaa63c..6a93460f1 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java @@ -12,13 +12,19 @@ import com.newrelic.api.agent.weaver.Weaver; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpRequest; import security.io.netty400.utils.NettyUtils; @Weave(type = MatchType.Interface, originalName = "io.netty.channel.ChannelOutboundHandler") public abstract class ChannelOutboundHandler_Instrumentation { public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - boolean isLockAcquired = NettyUtils.acquireNettyLockIfPossible(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND); + boolean isLockAcquired = false; + if (msg instanceof FullHttpResponse){ + isLockAcquired = NettyUtils.acquireNettyLockIfPossible(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND); + } if (isLockAcquired) { NettyUtils.processSecurityResponse(ctx, msg); NettyUtils.sendRXSSEvent(ctx, msg, getClass().getName(), NettyUtils.WRITE_METHOD_NAME); From 55ef6e43030eb6926af6303c5a6b1b5e8a23ee15 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 4 Mar 2024 18:36:57 +0530 Subject: [PATCH 056/124] NR-234865 : Fixed request processing checks & protocol name Co-authored-by: Lovesh Baya --- .../io/netty400/utils/NettyUtils.java | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java index 439e3d1c6..74ca605eb 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java @@ -1,7 +1,5 @@ package security.io.netty400.utils; -import com.newrelic.api.agent.NewRelic; -import com.newrelic.api.agent.Transaction; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; @@ -41,13 +39,10 @@ public class NettyUtils { public static void processSecurityRequest(ChannelHandlerContext ctx, Object msg, String className) { try { - Transaction tx = NewRelic.getAgent().getTransaction(); - Object secMetaObj = tx.getSecurityMetaData(); + if (!NewRelicSecurity.isHookProcessingActive()) { + return; + } if (msg instanceof HttpRequest) { - if (!(secMetaObj instanceof SecurityMetaData) || - NewRelicSecurity.getAgent().getSecurityMetaData() == null) { - return; - } SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); com.newrelic.api.agent.security.schema.HttpRequest securityRequest = securityMetaData.getRequest(); @@ -62,18 +57,15 @@ public static void processSecurityRequest(ChannelHandlerContext ctx, Object msg, processHttpRequestHeader((HttpRequest)msg, securityRequest); securityMetaData.setTracingHeaderValue(getTraceHeader(securityRequest.getHeaders())); - securityRequest.setProtocol(((HttpRequest) msg).getProtocolVersion().protocolName()); + securityRequest.setProtocol(((HttpRequest) msg).getProtocolVersion().protocolName().toLowerCase()); securityRequest.setContentType(securityRequest.getHeaders().get("content-type")); if (!securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(IO_NETTY)){ StackTraceElement[] stack = Thread.currentThread().getStackTrace(); securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(stack, 2, stack.length)); } securityRequest.setRequestParsed(true); - } else if (msg instanceof HttpContent) { - if (!(secMetaObj instanceof SecurityMetaData) || - NewRelicSecurity.getAgent().getSecurityMetaData() == null) { - return; - } + } + if (msg instanceof HttpContent) { Integer reqBodyTrackerContextId = NewRelicSecurity.getAgent().getSecurityMetaData() .getCustomAttribute(NR_SEC_CUSTOM_ATTRIB_NAME, Integer.class); if (reqBodyTrackerContextId == null) { From 5b4ec284caed927e7fe3e017941fe3539f2b7b77 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 4 Mar 2024 18:41:42 +0530 Subject: [PATCH 057/124] NR-234863 : Fixed and add more unit tests to netty support Co-authored-by: Lovesh Baya --- .../instrumentation/netty400/NettyServer.java | 82 ++++++++++++++++ .../instrumentation/netty400/NettyTest.java | 97 +++++++++++++------ 2 files changed, 148 insertions(+), 31 deletions(-) create mode 100644 instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyServer.java diff --git a/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyServer.java b/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyServer.java new file mode 100644 index 000000000..ea7a623be --- /dev/null +++ b/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyServer.java @@ -0,0 +1,82 @@ +package com.nr.agent.security.instrumentation.netty400; + +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.util.CharsetUtil; +import org.junit.rules.ExternalResource; + +import java.net.MalformedURLException; +import java.net.URL; + +public class NettyServer extends ExternalResource { + private Channel channel; + private int PORT; + + @Override + protected void before() throws Throwable { + PORT = SecurityInstrumentationTestRunner.getIntrospector().getRandomPort(); + startServer(); + } + + @Override + protected void after() { + stopServer(); + } + private void startServer() throws InterruptedException { + ServerBootstrap b = new ServerBootstrap(); + b.group(new NioEventLoopGroup(),new NioEventLoopGroup()) + .channel(NioServerSocketChannel.class) + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(Channel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast(new HttpServerCodec()); + pipeline.addLast(new HttpObjectAggregator(65536)); + pipeline.addLast(new SimpleChannelInboundHandler() { + @Override + protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest o) throws Exception { + o.content(); + FullHttpResponse response = new DefaultFullHttpResponse( + HttpVersion.HTTP_1_0, + HttpResponseStatus.OK, + Unpooled.copiedBuffer("write data", CharsetUtil.UTF_8)); + HttpHeaders.addHeader(response, HttpHeaders.Names.CONTENT_TYPE, "text/html"); + ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + } + }); + } + }); + + channel = b.bind(PORT).sync().channel(); + System.out.println("checking..."); + } + + private void stopServer(){ + if (channel.isActive() && channel.isOpen()){ + channel.close(); + } + } + public URL getEndPoint() throws MalformedURLException { + return new URL("http://localhost:" + PORT + "/"); + } +} diff --git a/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java b/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java index 4ceabeb60..23a4f9ed8 100644 --- a/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java +++ b/instrumentation-security/netty-4.0.0/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java @@ -1,12 +1,9 @@ package com.nr.agent.security.instrumentation.netty400; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; -import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.HttpRequest; import com.newrelic.api.agent.security.schema.HttpResponse; @@ -27,84 +24,110 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import org.junit.Assert; +import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import security.io.netty400.utils.NettyUtils; +import java.io.IOException; +import java.net.HttpURLConnection; import java.util.List; @RunWith(SecurityInstrumentationTestRunner.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @InstrumentationTestConfig(includePrefixes = {"security.io.netty400"}) public class NettyTest { + + @ClassRule + public static NettyServer server = new NettyServer(); + + private final String header = "text/html"; + @Test + public void testChannelRXSS() throws IOException { + connect(); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertFalse("No operations detected", operations.isEmpty()); + + RXSSOperation operation = (RXSSOperation) operations.get(0); + Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); + Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); + + HttpResponse response = introspector.getSecurityMetaData().getResponse(); + Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid response body", "write data", response.getResponseBody().toString()); + } @Test - public void testChannelRead() throws JsonProcessingException { + public void testChannelRead() { channelRead(); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("Operations detected", operations.size() == 0); + Assert.assertTrue("Operations detected", operations.isEmpty()); + HttpRequest request = introspector.getSecurityMetaData().getRequest(); - Assert.assertEquals("Invalid protocol", "HTTP", request.getProtocol()); + Assert.assertEquals("Invalid protocol", "http", request.getProtocol()); Assert.assertNotNull("No URL", request.getUrl()); - Assert.assertEquals("Invalid content-type", "text/html", request.getContentType()); - Assert.assertEquals("Invalid headers", "text/html", request.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "read data", request.getBody().toString()); + Assert.assertEquals("Invalid content-type", header, request.getContentType()); + Assert.assertEquals("Invalid headers", header, request.getHeaders().get("content-type")); + Assert.assertEquals("Invalid request body", "read data", request.getBody().toString()); } @Test - public void testWrite() throws JsonProcessingException { + public void testWrite() { write(); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); + Assert.assertFalse("No operations detected", operations.isEmpty()); RXSSOperation operation = (RXSSOperation) operations.get(0); Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); HttpResponse response = introspector.getSecurityMetaData().getResponse(); - Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); - Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); Assert.assertEquals("Invalid response body", "write data", response.getResponseBody().toString()); } @Test - public void testWriteAndFlush() throws JsonProcessingException { + public void testWriteAndFlush() { writeAndFlush(); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); + Assert.assertFalse("No operations detected", operations.isEmpty()); RXSSOperation operation = (RXSSOperation) operations.get(0); Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); HttpResponse response = introspector.getSecurityMetaData().getResponse(); - Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); - Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); Assert.assertEquals("Invalid response body", "write flush data", response.getResponseBody().toString()); } @Test - public void testWriteAndFlushPromise() throws JsonProcessingException { + public void testWriteAndFlushPromise() { writeAndFlushPromise(); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); + Assert.assertFalse("No operations detected", operations.isEmpty()); RXSSOperation operation = (RXSSOperation) operations.get(0); Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); HttpResponse response = introspector.getSecurityMetaData().getResponse(); - Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); - Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); Assert.assertEquals("Invalid response body", "write flush promise data", response.getResponseBody().toString()); } @@ -114,24 +137,25 @@ public void testEncode() { SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); + Assert.assertFalse("No operations detected", operations.isEmpty()); RXSSOperation operation = (RXSSOperation) operations.get(0); Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); HttpResponse response = introspector.getSecurityMetaData().getResponse(); - Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); - Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); Assert.assertEquals("Invalid response body", "encode data", response.getResponseBody().toString()); } @Trace(dispatcher = true) private void channelRead() { EmbeddedChannel channel = new EmbeddedChannel(new ChannelInboundHandlerAdapter()); - FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, "/test"); - httpRequest.headers().add("content-type", "text/html"); + FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.POST, "/test"); + httpRequest.headers().add("content-type", header); DefaultHttpContent httpContent = new DefaultHttpContent(Unpooled.wrappedBuffer("read data".getBytes())); +// httpRequest.content().writeBytes("read data".getBytes()); channel.writeInbound(httpRequest, httpContent); channel.read(); } @@ -140,7 +164,7 @@ private void channelRead() { private void write() { EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); - response.headers().add("content-type","text/html"); + response.headers().add("content-type", header); response.content().writeBytes("write data".getBytes()); channel.write(response); @@ -151,7 +175,7 @@ private void write() { private void writeAndFlush() { EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); - response.headers().add("content-type","text/html"); + response.headers().add("content-type", header); response.content().writeBytes("write flush data".getBytes()); channel.writeAndFlush(response); @@ -161,7 +185,7 @@ private void writeAndFlush() { private void writeAndFlushPromise() { EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); - response.headers().add("content-type","text/html"); + response.headers().add("content-type", header); response.content().writeBytes("write flush promise data".getBytes()); channel.writeAndFlush(response, channel.newPromise()); @@ -171,11 +195,22 @@ private void writeAndFlushPromise() { private void encode() { EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); channel.pipeline().addLast(new HttpResponseEncoder()); - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); - response.headers().add("content-type","text/html"); + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.ACCEPTED); + response.headers().add("content-type", header); response.content().writeBytes("encode data".getBytes()); channel.write(response); channel.flush(); } + @Trace(dispatcher = true) + private void connect() throws IOException { + HttpURLConnection connection = (HttpURLConnection) server.getEndPoint().openConnection(); + connection.setDoOutput(true); + connection.setRequestMethod("POST"); + connection.setRequestProperty("content-type", header); + connection.getOutputStream().write("name=ishi".getBytes()); + + connection.connect(); + System.out.println(connection.getResponseCode()); + } } \ No newline at end of file From b3b8d9264c14dc73973c595f05906e78bf889f6a Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 5 Mar 2024 09:35:56 +0530 Subject: [PATCH 058/124] NR-234867 : Fixed response processing checks Co-authored-by: Lovesh Baya --- .../main/java/security/io/netty400/utils/NettyUtils.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java index 74ca605eb..7905aa171 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java @@ -169,13 +169,7 @@ public static String getTraceHeader(Map headers) { public static void processSecurityResponse(ChannelHandlerContext ctx, Object msg) { try { - Transaction tx = NewRelic.getAgent().getTransaction(); - Object secMetaObj = tx.getSecurityMetaData(); - if (msg instanceof FullHttpResponse) { - if (!(secMetaObj instanceof SecurityMetaData) || - NewRelicSecurity.getAgent().getSecurityMetaData() == null) { - return; - } + if (NewRelicSecurity.isHookProcessingActive() && msg instanceof FullHttpResponse) { SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); com.newrelic.api.agent.security.schema.HttpResponse securityResponse = securityMetaData.getResponse(); From 2eec8730e8fd217f812467798d6c0c0983b8f150 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 5 Mar 2024 10:24:51 +0530 Subject: [PATCH 059/124] NR-238324 : detect netty server port on startup --- .../AbstractBootstrap_Instrumentation.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/bootstrap/AbstractBootstrap_Instrumentation.java diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/bootstrap/AbstractBootstrap_Instrumentation.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/bootstrap/AbstractBootstrap_Instrumentation.java new file mode 100644 index 000000000..fceb3c7e9 --- /dev/null +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/bootstrap/AbstractBootstrap_Instrumentation.java @@ -0,0 +1,31 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package security.io.netty400.bootstrap; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import io.netty.channel.ChannelFuture; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; + +@Weave(type = MatchType.ExactClass, originalName = "io.netty.bootstrap.AbstractBootstrap") +abstract class AbstractBootstrap_Instrumentation { + + @SuppressWarnings("unused") + private ChannelFuture doBind(final SocketAddress localAddress) { + if (localAddress instanceof InetSocketAddress) { + int port = ((InetSocketAddress) localAddress).getPort(); + NewRelicSecurity.getAgent().setApplicationConnectionConfig(port, "http"); + } + return Weaver.callOriginal(); + } + +} From f62791f8dd69c8b4c8053e4f84b396e475c599ff Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 5 Mar 2024 10:33:10 +0530 Subject: [PATCH 060/124] NR-238324 : separate instrumentation modules for 4.0.0 and 4.0.8 --- .../netty-4.0.0/build.gradle | 2 +- instrumentation-security/netty-4.0.8/.snyk | 30 +++ .../netty-4.0.8/build.gradle | 21 ++ .../AbstractBootstrap_Instrumentation.java | 31 +++ .../ChannelHandler_Instrumentation.java | 44 ++++ ...ChannelInboundHandler_Instrumentation.java | 42 +++ ...hannelOutboundHandler_Instrumentation.java | 40 +++ ...ChannelInboundHandler_Instrumentation.java | 23 ++ .../HttpObjectEncoder_Instrumentation.java | 26 ++ .../io/netty400/utils/NettyUtils.java | 244 ++++++++++++++++++ .../instrumentation/netty400/NettyTest.java | 181 +++++++++++++ settings.gradle | 1 + 12 files changed, 684 insertions(+), 1 deletion(-) create mode 100644 instrumentation-security/netty-4.0.8/.snyk create mode 100644 instrumentation-security/netty-4.0.8/build.gradle create mode 100644 instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/bootstrap/AbstractBootstrap_Instrumentation.java create mode 100644 instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelHandler_Instrumentation.java create mode 100644 instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java create mode 100644 instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java create mode 100644 instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java create mode 100644 instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/handler/codec/http/HttpObjectEncoder_Instrumentation.java create mode 100644 instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java create mode 100644 instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java diff --git a/instrumentation-security/netty-4.0.0/build.gradle b/instrumentation-security/netty-4.0.0/build.gradle index 2bfc0e0d1..a1ee29085 100644 --- a/instrumentation-security/netty-4.0.0/build.gradle +++ b/instrumentation-security/netty-4.0.0/build.gradle @@ -12,7 +12,7 @@ jar { } verifyInstrumentation { - passesOnly 'io.netty:netty-all:[4.0.0.Final,5.0.0.Alpha1)' + passesOnly 'io.netty:netty-all:[4.0.0.Final,4.0.8.Final)' } site { diff --git a/instrumentation-security/netty-4.0.8/.snyk b/instrumentation-security/netty-4.0.8/.snyk new file mode 100644 index 000000000..588e3c335 --- /dev/null +++ b/instrumentation-security/netty-4.0.8/.snyk @@ -0,0 +1,30 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.25.0 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JAVA-IONETTY-559515: + - '*': + reason: Instrumentation false positive + expires: 2038-01-19T00:00:00.000Z + created: 2022-11-03T16:37:15.223Z + SNYK-JAVA-IONETTY-559516: + - '*': + reason: Instrumentation false positive + expires: 2038-01-19T00:00:00.000Z + created: 2022-11-03T16:37:19.008Z + SNYK-JAVA-IONETTY-73571: + - '*': + reason: Instrumentation false positive + expires: 2038-01-19T00:00:00.000Z + created: 2022-11-03T16:37:22.194Z + SNYK-JAVA-ORGSCALALANG-3032987: + - '*': + reason: Instrumentation false positive + expires: 2038-01-19T00:00:00.000Z + created: 2022-11-03T16:37:25.428Z + SNYK-JAVA-IONETTY-473214: + - '*': + reason: Instrumentation false positive + expires: 2038-01-19T00:00:00.000Z + created: 2022-11-11T14:10:14.681Z +patch: {} diff --git a/instrumentation-security/netty-4.0.8/build.gradle b/instrumentation-security/netty-4.0.8/build.gradle new file mode 100644 index 000000000..ec8a24b71 --- /dev/null +++ b/instrumentation-security/netty-4.0.8/build.gradle @@ -0,0 +1,21 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("io.netty:netty-all:4.0.0.Final") +} + +jar { + manifest { + attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.netty-4.0.0' + } +} + +verifyInstrumentation { + passesOnly 'io.netty:netty-all:[4.0.8.Final,5.0.0.Alpha1)' +} + +site { + title 'Netty' + type 'Appserver' +} \ No newline at end of file diff --git a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/bootstrap/AbstractBootstrap_Instrumentation.java b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/bootstrap/AbstractBootstrap_Instrumentation.java new file mode 100644 index 000000000..2c9a7cb88 --- /dev/null +++ b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/bootstrap/AbstractBootstrap_Instrumentation.java @@ -0,0 +1,31 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package security.io.netty400.bootstrap; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import io.netty.channel.ChannelFuture; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; + +@Weave(type = MatchType.ExactClass, originalName = "io.netty.bootstrap.AbstractBootstrap") +public abstract class AbstractBootstrap_Instrumentation { + + @SuppressWarnings("unused") + private ChannelFuture doBind(final SocketAddress localAddress) { + if (localAddress instanceof InetSocketAddress) { + int port = ((InetSocketAddress) localAddress).getPort(); + NewRelicSecurity.getAgent().setApplicationConnectionConfig(port, "http"); + } + return Weaver.callOriginal(); + } + +} diff --git a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelHandler_Instrumentation.java b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelHandler_Instrumentation.java new file mode 100644 index 000000000..e12227199 --- /dev/null +++ b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelHandler_Instrumentation.java @@ -0,0 +1,44 @@ +/* + * + * * Copyright 2022 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ +package security.io.netty400.channel; + +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import io.netty.channel.ChannelHandlerContext; + +@Weave(type = MatchType.Interface, originalName = "io.netty.channel.ChannelHandler") +public class ChannelHandler_Instrumentation { + + /* + * This is to solve a bug where the transaction is lost when spring webclient times out and throws an error + * using the io.netty.handler.timeout.ReadTimeoutHandler class from netty. + * + * Any extra handlers used by netty will now link a transaction if available. + * + * ----------------------------------- + * WARNING + * ----------------------------------- + * + * Netty has marked this method as deprecated since 4.1 + * + * If instrumentation verification fails for because of this class, + * then in the new instrumentation module try instrumenting the class: + * + * io.netty.channel.AbstractChannelHandlerContext + * + * and its method: + * + * static void invokeExceptionCaught(final AbstractChannelHandlerContext next, final Throwable cause) + * + * */ + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + // TODO : Negative RXSS case. Read response. + Weaver.callOriginal(); + } + +} diff --git a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java new file mode 100644 index 000000000..10c000dc3 --- /dev/null +++ b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelInboundHandler_Instrumentation.java @@ -0,0 +1,42 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package security.io.netty400.channel; + +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpRequest; +import security.io.netty400.utils.NettyUtils; + +@Weave(type = MatchType.Interface, originalName = "io.netty.channel.ChannelInboundHandler") +public abstract class ChannelInboundHandler_Instrumentation { + + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + boolean isLockAcquired = false; + if (msg instanceof HttpRequest || msg instanceof HttpContent){ + isLockAcquired = NettyUtils.acquireNettyLockIfPossible(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK); + } + if (isLockAcquired) { + NettyUtils.processSecurityRequest(ctx, msg, getClass().getName()); + if (!StringUtils.startsWith(getClass().getName(), NettyUtils.IO_NETTY)) { + ServletHelper.registerUserLevelCode(NettyUtils.IO_NETTY); + } + } + try { + Weaver.callOriginal(); + } finally { + if (isLockAcquired) { + NettyUtils.releaseNettyLock(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK); + } + } + } +} diff --git a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java new file mode 100644 index 000000000..6a93460f1 --- /dev/null +++ b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/ChannelOutboundHandler_Instrumentation.java @@ -0,0 +1,40 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package security.io.netty400.channel; + +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpRequest; +import security.io.netty400.utils.NettyUtils; + +@Weave(type = MatchType.Interface, originalName = "io.netty.channel.ChannelOutboundHandler") +public abstract class ChannelOutboundHandler_Instrumentation { + + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + boolean isLockAcquired = false; + if (msg instanceof FullHttpResponse){ + isLockAcquired = NettyUtils.acquireNettyLockIfPossible(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND); + } + if (isLockAcquired) { + NettyUtils.processSecurityResponse(ctx, msg); + NettyUtils.sendRXSSEvent(ctx, msg, getClass().getName(), NettyUtils.WRITE_METHOD_NAME); + } + try { + Weaver.callOriginal(); + } finally { + if (isLockAcquired) { + NettyUtils.releaseNettyLock(NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND); + } + } + } +} diff --git a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java new file mode 100644 index 000000000..b82cf5af4 --- /dev/null +++ b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/channel/SimpleChannelInboundHandler_Instrumentation.java @@ -0,0 +1,23 @@ +package security.io.netty400.channel; + +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import io.netty.channel.ChannelHandlerContext; +import security.io.netty400.utils.NettyUtils; + +@Weave(type = MatchType.BaseClass, originalName = "io.netty.channel.SimpleChannelInboundHandler") +public class SimpleChannelInboundHandler_Instrumentation { + + protected void channelRead0(ChannelHandlerContext ctx, I msg) throws Exception { + try { + if (!StringUtils.startsWith(getClass().getName(), NettyUtils.IO_NETTY)) { + ServletHelper.registerUserLevelCode(NettyUtils.IO_NETTY); + } + } catch (Exception e){ + } + Weaver.callOriginal(); + } +} diff --git a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/handler/codec/http/HttpObjectEncoder_Instrumentation.java b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/handler/codec/http/HttpObjectEncoder_Instrumentation.java new file mode 100644 index 000000000..c4b1e1779 --- /dev/null +++ b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/handler/codec/http/HttpObjectEncoder_Instrumentation.java @@ -0,0 +1,26 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package security.io.netty400.handler.codec.http; + +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import io.netty.channel.ChannelHandlerContext; + +import java.util.List; + +@Weave(type = MatchType.BaseClass, originalName = "io.netty.handler.codec.http.HttpObjectEncoder") +public class HttpObjectEncoder_Instrumentation { + + // heading downstream + protected void encode(ChannelHandlerContext ctx, Object msg, List out) { + // TODO : Process response here + Weaver.callOriginal(); + } + +} diff --git a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java new file mode 100644 index 000000000..7905aa171 --- /dev/null +++ b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java @@ -0,0 +1,244 @@ +package security.io.netty400.utils; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.RXSSOperation; +import com.newrelic.api.agent.security.schema.policy.AgentPolicy; +import com.newrelic.api.agent.security.utils.logging.LogLevel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class NettyUtils { + public static final String NETTY_4_0_0 = "NETTY-4.0.0"; + public static String NR_SEC_CUSTOM_ATTRIB_NAME = "NETTY-4.8-REQ-BODY-TRACKER"; + public static String NR_SEC_NETTY_OPERATIONAL_LOCK = "NR_SEC_NETTY_OPERATIONAL_LOCK_INBOUND"; + public static String NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND = "NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND"; + private static final String X_FORWARDED_FOR = "x-forwarded-for"; + private static final String EMPTY = ""; + public static final String WRITE_METHOD_NAME = "write"; + + public static final String IO_NETTY = "io.netty."; + private static final String ERROR_GETTING_SERVER_PORT = "Instrumentation library: %s , error while getting server port %s"; + private static final String ERROR_PARSING_HTTP_RESPONSE_DATA = "Instrumentation library: %s , error while parsing HTTP response data : %s"; + + public static void processSecurityRequest(ChannelHandlerContext ctx, Object msg, String className) { + try { + if (!NewRelicSecurity.isHookProcessingActive()) { + return; + } + if (msg instanceof HttpRequest) { + SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + com.newrelic.api.agent.security.schema.HttpRequest securityRequest = + securityMetaData.getRequest(); + + if (!NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() && securityRequest.isRequestParsed()) { + return; + } + securityRequest.setMethod(((HttpRequest) msg).getMethod().name()); + securityRequest.setUrl(((HttpRequest) msg).getUri()); + setClientAddressDetails(securityMetaData, ctx.channel().remoteAddress().toString()); + setServerPortDetails(securityRequest, ctx.channel().localAddress().toString()); + processHttpRequestHeader((HttpRequest)msg, securityRequest); + securityMetaData.setTracingHeaderValue(getTraceHeader(securityRequest.getHeaders())); + + securityRequest.setProtocol(((HttpRequest) msg).getProtocolVersion().protocolName().toLowerCase()); + securityRequest.setContentType(securityRequest.getHeaders().get("content-type")); + if (!securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(IO_NETTY)){ + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(stack, 2, stack.length)); + } + securityRequest.setRequestParsed(true); + } + if (msg instanceof HttpContent) { + Integer reqBodyTrackerContextId = NewRelicSecurity.getAgent().getSecurityMetaData() + .getCustomAttribute(NR_SEC_CUSTOM_ATTRIB_NAME, Integer.class); + if (reqBodyTrackerContextId == null) { + reqBodyTrackerContextId = ctx.hashCode(); + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(NR_SEC_CUSTOM_ATTRIB_NAME, reqBodyTrackerContextId); + } + if (reqBodyTrackerContextId.equals(ctx.hashCode())) { + com.newrelic.api.agent.security.schema.HttpRequest securityRequest = + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest(); + securityRequest.getBody().append(((HttpContent) msg).content().toString(StandardCharsets.UTF_8)); + } + } + } catch (Throwable ignored) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_PARSING_HTTP_REQUEST_DATA, NETTY_4_0_0, ignored.getMessage()), ignored, NettyUtils.class.getName()); + } + } + + private static void setServerPortDetails(com.newrelic.api.agent.security.schema.HttpRequest securityRequest, String address) { + try { + String port = StringUtils.substringAfterLast(address, ":"); + if (StringUtils.isBlank(port)) { + return; + } + securityRequest.setServerPort(Integer.parseInt(port)); + } catch (Throwable throwable) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(ERROR_GETTING_SERVER_PORT, NETTY_4_0_0, throwable.getMessage()), throwable, NettyUtils.class.getName()); + } + } + + private static void setClientAddressDetails(SecurityMetaData securityMetaData, String address) { + if (StringUtils.isBlank(address)) { + return; + } + com.newrelic.api.agent.security.schema.HttpRequest securityRequest = securityMetaData.getRequest(); + address = StringUtils.replace(address, "/", ""); + securityRequest.setClientIP(StringUtils.substringBeforeLast(address, ":")); + securityRequest.setClientPort(StringUtils.substringAfterLast(address, ":")); + if (StringUtils.isNotBlank(securityRequest.getClientIP())) { + securityMetaData.getMetaData().getIps().add(securityRequest.getClientIP()); + } + } + + public static void processHttpRequestHeader(HttpRequest request, com.newrelic.api.agent.security.schema.HttpRequest securityRequest) { + Set headerNames = request.headers().names(); + for (String headerKey : headerNames) { + boolean takeNextValue = false; + if (headerKey != null) { + headerKey = headerKey.toLowerCase(); + } + AgentPolicy agentPolicy = NewRelicSecurity.getAgent().getCurrentPolicy(); + AgentMetaData agentMetaData = NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData(); + if (agentPolicy != null + && agentPolicy.getProtectionMode().getEnabled() + && agentPolicy.getProtectionMode().getIpBlocking().getEnabled() + && agentPolicy.getProtectionMode().getIpBlocking().getIpDetectViaXFF() + && X_FORWARDED_FOR.equals(headerKey)) { + takeNextValue = true; + } else if (ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.equals(headerKey)) { + // TODO: May think of removing this intermediate obj and directly create K2 Identifier. + NewRelicSecurity.getAgent().getSecurityMetaData().setFuzzRequestIdentifier(ServletHelper.parseFuzzRequestIdentifierHeader(request.headers().get(headerKey))); + } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.headers().get(headerKey)); + } + + String headerFullValue = EMPTY; + List headerElements = request.headers().getAll(headerKey); + for (String headerValue : headerElements) { + if (headerValue != null && !headerValue.trim().isEmpty()) { + if (takeNextValue) { + agentMetaData.setClientDetectedFromXFF(true); + securityRequest.setClientIP(headerValue); + agentMetaData.getIps() + .add(securityRequest.getClientIP()); + securityRequest.setClientPort(EMPTY); + takeNextValue = false; + } + if (headerFullValue.trim().isEmpty()) { + headerFullValue = headerValue; + } else { + headerFullValue = String.join(";", headerFullValue, headerValue); + } + } + } + securityRequest.getHeaders().put(headerKey, headerFullValue); + } + + } + + public static String getTraceHeader(Map headers) { + String data = EMPTY; + if (headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER) || headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())) { + data = headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER); + if (data == null || data.trim().isEmpty()) { + data = headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()); + } + } + return data; + } + + public static void processSecurityResponse(ChannelHandlerContext ctx, Object msg) { + try { + if (NewRelicSecurity.isHookProcessingActive() && msg instanceof FullHttpResponse) { + SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + com.newrelic.api.agent.security.schema.HttpResponse securityResponse = + securityMetaData.getResponse(); + processResponseHeaders((HttpResponse) msg, securityResponse); + securityResponse.setResponseContentType(((FullHttpResponse) msg).headers().get(HttpHeaders.Names.CONTENT_TYPE)); + securityResponse.getResponseBody().append(((FullHttpResponse) msg).content().toString(StandardCharsets.UTF_8)); + } + } catch (Throwable e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(ERROR_PARSING_HTTP_RESPONSE_DATA, NETTY_4_0_0, e.getMessage()), e, NettyUtils.class.getName()); + } + } + + public static void sendRXSSEvent(ChannelHandlerContext ctx, Object msg, String className, String methodName) { + try { + if (!NewRelicSecurity.isHookProcessingActive() || !(msg instanceof FullHttpResponse)) { + return; + } + //Add request URI hash to low severity event filter + LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); + + if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { + RXSSOperation rxssOperation = new RXSSOperation(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest(), + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse(), + className, methodName); + NewRelicSecurity.getAgent().registerOperation(rxssOperation); + } + ServletHelper.tmpFileCleanUp(NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getTempFiles()); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, NETTY_4_0_0, e.getMessage()), e, NettyUtils.class.getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, NETTY_4_0_0, e.getMessage()), e, NettyUtils.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, NETTY_4_0_0, e.getMessage()), e, NettyUtils.class.getName()); + } + } + + private static void processResponseHeaders(HttpResponse response, com.newrelic.api.agent.security.schema.HttpResponse securityResponse) { + for (Map.Entry entry : response.headers().entries()) { + String headerKey = entry.getKey().toLowerCase(); + String headerValue = entry.getValue(); + securityResponse.getHeaders().put(headerKey, headerValue); + } + } + + public static boolean isNettyLockAcquired(String operationLock) { + try { + return NewRelicSecurity.isHookProcessingActive() && + Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(operationLock + Thread.currentThread().getId(), Boolean.class)); + } catch (Throwable ignored) {} + return false; + } + + public static boolean acquireNettyLockIfPossible(String operationLock) { + try { + if (NewRelicSecurity.isHookProcessingActive() && + !isNettyLockAcquired(operationLock)) { + NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(operationLock + Thread.currentThread().getId(), true); + return true; + } + } catch (Throwable ignored){} + return false; + } + + public static void releaseNettyLock(String operationLock) { + try { + if(NewRelicSecurity.isHookProcessingActive()) { + NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(operationLock + Thread.currentThread().getId(), null); + } + } catch (Throwable ignored){} + } +} diff --git a/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java b/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java new file mode 100644 index 000000000..4ceabeb60 --- /dev/null +++ b/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java @@ -0,0 +1,181 @@ +package com.nr.agent.security.instrumentation.netty400; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.newrelic.agent.security.introspec.InstrumentationTestConfig; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import com.newrelic.agent.security.introspec.SecurityIntrospector; +import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.HttpRequest; +import com.newrelic.api.agent.security.schema.HttpResponse; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; +import com.newrelic.api.agent.security.schema.operation.RXSSOperation; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelInboundHandlerAdapter; + +import io.netty.channel.ChannelOutboundHandlerAdapter; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.DefaultHttpContent; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpResponseEncoder; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import security.io.netty400.utils.NettyUtils; + +import java.util.List; + +@RunWith(SecurityInstrumentationTestRunner.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@InstrumentationTestConfig(includePrefixes = {"security.io.netty400"}) +public class NettyTest { + @Test + public void testChannelRead() throws JsonProcessingException { + channelRead(); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertTrue("Operations detected", operations.size() == 0); + HttpRequest request = introspector.getSecurityMetaData().getRequest(); + Assert.assertEquals("Invalid protocol", "HTTP", request.getProtocol()); + Assert.assertNotNull("No URL", request.getUrl()); + Assert.assertEquals("Invalid content-type", "text/html", request.getContentType()); + Assert.assertEquals("Invalid headers", "text/html", request.getHeaders().get("content-type")); + Assert.assertEquals("Invalid response body", "read data", request.getBody().toString()); + } + + @Test + public void testWrite() throws JsonProcessingException { + write(); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertTrue("No operations detected", operations.size() > 0); + + RXSSOperation operation = (RXSSOperation) operations.get(0); + Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); + Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); + + HttpResponse response = introspector.getSecurityMetaData().getResponse(); + Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid response body", "write data", response.getResponseBody().toString()); + } + + @Test + public void testWriteAndFlush() throws JsonProcessingException { + writeAndFlush(); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertTrue("No operations detected", operations.size() > 0); + + RXSSOperation operation = (RXSSOperation) operations.get(0); + Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); + Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); + + HttpResponse response = introspector.getSecurityMetaData().getResponse(); + Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid response body", "write flush data", response.getResponseBody().toString()); + } + + @Test + public void testWriteAndFlushPromise() throws JsonProcessingException { + writeAndFlushPromise(); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertTrue("No operations detected", operations.size() > 0); + + RXSSOperation operation = (RXSSOperation) operations.get(0); + Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); + Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); + + HttpResponse response = introspector.getSecurityMetaData().getResponse(); + Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid response body", "write flush promise data", response.getResponseBody().toString()); + } + + @Test + public void testEncode() { + encode(); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertTrue("No operations detected", operations.size() > 0); + + RXSSOperation operation = (RXSSOperation) operations.get(0); + Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); + Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); + + HttpResponse response = introspector.getSecurityMetaData().getResponse(); + Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid response body", "encode data", response.getResponseBody().toString()); + } + + @Trace(dispatcher = true) + private void channelRead() { + EmbeddedChannel channel = new EmbeddedChannel(new ChannelInboundHandlerAdapter()); + FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, "/test"); + httpRequest.headers().add("content-type", "text/html"); + DefaultHttpContent httpContent = new DefaultHttpContent(Unpooled.wrappedBuffer("read data".getBytes())); + channel.writeInbound(httpRequest, httpContent); + channel.read(); + } + + @Trace(dispatcher = true) + private void write() { + EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); + response.headers().add("content-type","text/html"); + response.content().writeBytes("write data".getBytes()); + + channel.write(response); + channel.flush(); + } + + @Trace(dispatcher = true) + private void writeAndFlush() { + EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); + response.headers().add("content-type","text/html"); + response.content().writeBytes("write flush data".getBytes()); + + channel.writeAndFlush(response); + } + + @Trace(dispatcher = true) + private void writeAndFlushPromise() { + EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); + response.headers().add("content-type","text/html"); + response.content().writeBytes("write flush promise data".getBytes()); + + channel.writeAndFlush(response, channel.newPromise()); + } + + @Trace(dispatcher = true) + private void encode() { + EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); + channel.pipeline().addLast(new HttpResponseEncoder()); + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); + response.headers().add("content-type","text/html"); + response.content().writeBytes("encode data".getBytes()); + + channel.write(response); + channel.flush(); + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 86ddb310e..c2c3c2596 100644 --- a/settings.gradle +++ b/settings.gradle @@ -119,6 +119,7 @@ include 'instrumentation:akka-http-2.11_10.0.0' include 'instrumentation:jetty-9' include 'instrumentation:jetty-11' include 'instrumentation:netty-4.0.0' +include 'instrumentation:netty-4.0.8' //include 'instrumentation:grpc-1.40.0' include 'instrumentation:dynamodb-1.11.80' include 'instrumentation:dynamodb-1.11.390' From e3db96077e62016f22cda480e5e99155f23ace69 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 5 Mar 2024 10:50:40 +0530 Subject: [PATCH 061/124] Updated build.gradle --- instrumentation-security/netty-4.0.8/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation-security/netty-4.0.8/build.gradle b/instrumentation-security/netty-4.0.8/build.gradle index ec8a24b71..9dcbb5235 100644 --- a/instrumentation-security/netty-4.0.8/build.gradle +++ b/instrumentation-security/netty-4.0.8/build.gradle @@ -2,12 +2,12 @@ dependencies { implementation(project(":newrelic-security-api")) implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") - implementation("io.netty:netty-all:4.0.0.Final") + implementation("io.netty:netty-all:4.0.8.Final") } jar { manifest { - attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.netty-4.0.0' + attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.netty-4.0.8' } } From 294b59c770230b34b62d84d754e0a2afa1aeb972 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 6 Mar 2024 13:51:23 +0530 Subject: [PATCH 062/124] Fix for incorrect user class and stack trace in RXSS events --- .../http/scaladsl/server/AkkaCoreUtils.java | 2 +- .../servlet/FilterChain_Instrumentation.java | 2 +- .../javax/servlet/Filter_Instrumentation.java | 2 +- .../javax/servlet/Servlet_Instrumentation.java | 2 +- .../servlet/FilterChain_Instrumentation.java | 2 +- .../jakarta/servlet/Filter_Instrumentation.java | 2 +- .../servlet/Servlet_Instrumentation.java | 2 +- .../servlet/FilterChain_Instrumentation.java | 2 +- .../jakarta/servlet/Filter_Instrumentation.java | 2 +- .../servlet/Servlet_Instrumentation.java | 2 +- .../SpringController_Instrumentation.java | 1 + .../com/newrelic/api/agent/security/Agent.java | 3 ++- .../instrumentation/helpers/ServletHelper.java | 17 ++++++++++++++++- .../agent/security/schema/AgentMetaData.java | 14 ++++++++++++++ 14 files changed, 43 insertions(+), 12 deletions(-) diff --git a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java index 5aa9083d8..d3fafaa44 100644 --- a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java @@ -61,7 +61,7 @@ public static boolean acquireServletLockIfPossible() { public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, String className, String methodName, Token token) { try { token.linkAndExpire(); - if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive()){ + if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)){ return; } NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(contentType); diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java index 1caf929a4..fd9963357 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java @@ -91,7 +91,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() + if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) ) { return; } diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java index 2540b23f0..35614c366 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java @@ -92,7 +92,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() + if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) ) { return; } diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java index 39c27b4d6..94f4c0f91 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java @@ -97,7 +97,7 @@ private void preprocessSecurityHook(ServletRequest_Instrumentation request, Serv private void postProcessSecurityHook(ServletRequest_Instrumentation request, ServletResponse_Instrumentation response) { try { - if (!NewRelicSecurity.isHookProcessingActive() + if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) ) { return; } diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java index e3414be3c..a6c1d9563 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java @@ -90,7 +90,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() + if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) ) { return; } diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java index 54c81187e..906c67788 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java @@ -92,7 +92,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() + if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) ) { return; } diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java index 4ec1c91bd..082a936f6 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java @@ -96,7 +96,7 @@ private void preprocessSecurityHook(ServletRequest_Instrumentation request, Serv private void postProcessSecurityHook(ServletRequest_Instrumentation request, ServletResponse_Instrumentation response) { try { - if (!NewRelicSecurity.isHookProcessingActive() + if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) ) { return; } diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java index ba39efeb2..d85a2526e 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java @@ -91,7 +91,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() + if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) ) { return; } diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java index 59d8e0f63..bb9bba21a 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java @@ -92,7 +92,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() + if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) ) { return; } diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java index 46bc01e24..cad1e130b 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java @@ -96,7 +96,7 @@ private void preprocessSecurityHook(ServletRequest_Instrumentation request, Serv private void postProcessSecurityHook(ServletRequest_Instrumentation request, ServletResponse_Instrumentation response) { try { - if (!NewRelicSecurity.isHookProcessingActive() + if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) ) { return; } diff --git a/instrumentation-security/spring-web/src/main/java/com/newrelic/agent/security/instrumentation/springweb/SpringController_Instrumentation.java b/instrumentation-security/spring-web/src/main/java/com/newrelic/agent/security/instrumentation/springweb/SpringController_Instrumentation.java index 9776c311c..696ff25b9 100644 --- a/instrumentation-security/spring-web/src/main/java/com/newrelic/agent/security/instrumentation/springweb/SpringController_Instrumentation.java +++ b/instrumentation-security/spring-web/src/main/java/com/newrelic/agent/security/instrumentation/springweb/SpringController_Instrumentation.java @@ -28,6 +28,7 @@ public class SpringController_Instrumentation { @WeaveIntoAllMethods private static void requestMapping() { ServletHelper.registerUserLevelCode("spring-annotation"); + ServletHelper.setFoundAnnotedUserLevelServiceMethod(); } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index 9f1c35242..59956c3f3 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -271,6 +271,7 @@ public void registerOperation(AbstractOperation operation) { } if (operation instanceof RXSSOperation) { operation.setStackTrace(securityMetaData.getMetaData().getServiceTrace()); + securityMetaData.addCustomAttribute("RXSS_PROCESSED", true); } else { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); operation.setStackTrace(Arrays.copyOfRange(trace, 2, trace.length)); @@ -411,7 +412,7 @@ private static void processStackTrace(AbstractOperation operation) { markedForRemoval = false; // Only remove consecutive top com.newrelic and com.nr. elements from stack. - if (i - 1 == j && StringUtils.startsWithAny(stackTrace[i].getClassName(), "com.newrelic.", "com.nr.")) { + if (i - 1 == j && StringUtils.startsWithAny(stackTrace[i].getClassName(), "com.newrelic.agent.security.", "com.newrelic.api.agent.")) { resetFactor++; j++; markedForRemoval = true; diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java index df4fe1ee2..e28a103e5 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java @@ -153,8 +153,9 @@ public static boolean registerUserLevelCode(String frameworkName, boolean asyncC return false; } SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); - if (!securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(frameworkName)) { + if (!securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(frameworkName) || !securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod()) { securityMetaData.getMetaData().setUserLevelServiceMethodEncountered(true); + securityMetaData.getMetaData().setUserLevelServiceMethodEncounteredFramework(frameworkName); StackTraceElement[] trace = Thread.currentThread().getStackTrace(); securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(trace, asyncContext?2:3, trace.length)); return true; @@ -164,6 +165,20 @@ public static boolean registerUserLevelCode(String frameworkName, boolean asyncC return false; } + public static boolean setFoundAnnotedUserLevelServiceMethod() { + try { + if (!NewRelicSecurity.isHookProcessingActive() || (NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty()) + ) { + return false; + } + SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + securityMetaData.getMetaData().setFoundAnnotedUserLevelServiceMethod(true); + return true; + } catch (Throwable ignored){ + } + return false; + } + public static Set getFilesToRemove() { return filesToRemove; diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java index 751f4d24f..2d0186f68 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java @@ -32,9 +32,15 @@ public class AgentMetaData { @JsonIgnore private boolean userLevelServiceMethodEncountered = false; + public void setUserLevelServiceMethodEncounteredFramework(String userLevelServiceMethodEncounteredFramework) { + this.userLevelServiceMethodEncounteredFramework = userLevelServiceMethodEncounteredFramework; + } + @JsonIgnore private String userLevelServiceMethodEncounteredFramework; + private boolean foundAnnotedUserLevelServiceMethod = false; + @JsonIgnore private Set ips; @@ -170,4 +176,12 @@ public AppServerInfo getAppServerInfo() { public void setAppServerInfo(AppServerInfo appServerInfo) { this.appServerInfo = appServerInfo; } + + public boolean isFoundAnnotedUserLevelServiceMethod() { + return foundAnnotedUserLevelServiceMethod; + } + + public void setFoundAnnotedUserLevelServiceMethod(boolean foundAnnotedUserLevelServiceMethod) { + this.foundAnnotedUserLevelServiceMethod = foundAnnotedUserLevelServiceMethod; + } } From b0026f1e833184b2448b9173e04d743c34cb8a2a Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 6 Mar 2024 17:28:22 +0530 Subject: [PATCH 063/124] Fix NPE generated due to getCustomAttribute(String, java.lang.Class) --- .../src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java | 2 +- .../main/java/javax/servlet/FilterChain_Instrumentation.java | 2 +- .../src/main/java/javax/servlet/Filter_Instrumentation.java | 2 +- .../src/main/java/javax/servlet/Servlet_Instrumentation.java | 2 +- .../main/java/jakarta/servlet/FilterChain_Instrumentation.java | 2 +- .../src/main/java/jakarta/servlet/Filter_Instrumentation.java | 2 +- .../src/main/java/jakarta/servlet/Servlet_Instrumentation.java | 2 +- .../main/java/jakarta/servlet/FilterChain_Instrumentation.java | 2 +- .../src/main/java/jakarta/servlet/Filter_Instrumentation.java | 2 +- .../src/main/java/jakarta/servlet/Servlet_Instrumentation.java | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java index d3fafaa44..71109bdb9 100644 --- a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java @@ -61,7 +61,7 @@ public static boolean acquireServletLockIfPossible() { public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, String className, String methodName, Token token) { try { token.linkAndExpire(); - if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)){ + if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class))){ return; } NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(contentType); diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java index fd9963357..2e25a599f 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/FilterChain_Instrumentation.java @@ -91,7 +91,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) + if (!NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)) ) { return; } diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java index 35614c366..6acac817c 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Filter_Instrumentation.java @@ -92,7 +92,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) + if (!NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)) ) { return; } diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java index 94f4c0f91..98f957d36 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/Servlet_Instrumentation.java @@ -97,7 +97,7 @@ private void preprocessSecurityHook(ServletRequest_Instrumentation request, Serv private void postProcessSecurityHook(ServletRequest_Instrumentation request, ServletResponse_Instrumentation response) { try { - if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) + if (!NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)) ) { return; } diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java index a6c1d9563..9893b7ccf 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java @@ -90,7 +90,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) + if (!NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)) ) { return; } diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java index 906c67788..cf4ddbeb9 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java @@ -92,7 +92,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) + if (!NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)) ) { return; } diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java index 082a936f6..01da21d98 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java @@ -96,7 +96,7 @@ private void preprocessSecurityHook(ServletRequest_Instrumentation request, Serv private void postProcessSecurityHook(ServletRequest_Instrumentation request, ServletResponse_Instrumentation response) { try { - if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) + if (!NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)) ) { return; } diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java index d85a2526e..c7f7a3c45 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/FilterChain_Instrumentation.java @@ -91,7 +91,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) + if (!NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)) ) { return; } diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java index bb9bba21a..d1d36a341 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Filter_Instrumentation.java @@ -92,7 +92,7 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { - if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) + if (!NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)) ) { return; } diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java index cad1e130b..cc01075f3 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/Servlet_Instrumentation.java @@ -96,7 +96,7 @@ private void preprocessSecurityHook(ServletRequest_Instrumentation request, Serv private void postProcessSecurityHook(ServletRequest_Instrumentation request, ServletResponse_Instrumentation response) { try { - if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class) + if (!NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)) ) { return; } From 5dbd3dc6b58b4cee8d1ec9146383d98b5afb38eb Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 11 Mar 2024 18:28:43 +0530 Subject: [PATCH 064/124] NR-234900 : Add instrumentation to setObject of prepared statement Remove null entries from rci method calls fix isEmpty check for SQL operation --- .../PreparedStatement_Instrumentation.java | 51 +++++++++++++++++++ .../instrumentator/dispatcher/Dispatcher.java | 9 ++++ .../newrelic/api/agent/security/Agent.java | 2 +- .../agent/security/schema/AgentMetaData.java | 4 +- .../schema/operation/SQLOperation.java | 13 ++++- 5 files changed, 75 insertions(+), 4 deletions(-) diff --git a/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java b/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java index 0690ce8f6..a6af2b84b 100644 --- a/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java +++ b/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java @@ -22,6 +22,7 @@ import com.newrelic.api.agent.weaver.Weaver; import java.math.BigDecimal; +import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; @@ -32,6 +33,9 @@ public abstract class PreparedStatement_Instrumentation { @NewField private Map params; + + @NewField + private Map objectParams; @NewField String preparedSql; @NewField @@ -236,6 +240,43 @@ public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { Weaver.callOriginal(); } + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + setParamValue(parameterIndex, xmlObject.getString()); + Weaver.callOriginal(); + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + setParamValue(parameterIndex, x.toString()); + Weaver.callOriginal(); + } + + public void setURL(int parameterIndex, java.net.URL x) throws SQLException { + setParamValue(parameterIndex, x.toString()); + Weaver.callOriginal(); + } + + public void setArray (int parameterIndex, Array x) throws SQLException { + setObjectParams(parameterIndex, x.getArray()); + Weaver.callOriginal(); + } + + public void setObject(int parameterIndex, Object x) throws SQLException { + if(x instanceof Long || x instanceof Integer || x instanceof Double || + x instanceof Float || x instanceof Boolean || x instanceof Short || + x instanceof String || x instanceof byte[] || x instanceof Timestamp || + x instanceof Date || x instanceof BigDecimal || x instanceof Time) { + setParamValue(parameterIndex, x); + } else if (x instanceof SQLXML) { + setParamValue(parameterIndex, ((SQLXML) x).getString()); + } else if (x instanceof RowId || x instanceof URL) { + setParamValue(parameterIndex, x.toString()); + } else { + //TODO critical-message for inconvertible + setObjectParams(parameterIndex, x); + } + Weaver.callOriginal(); + } + public void clearParameters() throws SQLException { if(params != null){ params.clear(); @@ -260,6 +301,13 @@ private void setParamValue(int index, byte[] value) { params.put(String.valueOf(index), new String(value)); } + private void setObjectParams(int index, Object data) { + if (objectParams == null) { + objectParams = new HashMap<>(); + } + + objectParams.put(String.valueOf(index), data); + } public void addBatch() throws SQLException { boolean isLockAcquired = acquireLockIfPossible(); SQLOperation sqlOperation = null; @@ -269,6 +317,9 @@ public void addBatch() throws SQLException { Map localParams = new HashMap<>(); localParams.putAll(params); sqlOperation.setParams(localParams); + Map localObjParams = new HashMap<>(); + localObjParams.putAll(objectParams); + sqlOperation.setObjectParams(localObjParams); sqlOperation.setDbName(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(JDBCVendor.META_CONST_JDBC_VENDOR, String.class)); sqlOperation.setPreparedCall(true); if(batchSQLOperation==null) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java index a2a04577a..f9755809a 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java @@ -510,6 +510,15 @@ private JavaAgentEventBean prepareSQLDbCommandEvent(SQLOperation operation, if(operation.getParams() != null) { query.put(PARAMETERS, new JSONObject(operation.getParams())); } + if(operation.getObjectParams() != null && !operation.getObjectParams().isEmpty()){ + JSONObject jsonObject = (JSONObject) query.get(PARAMETERS); + if(jsonObject == null){ + query.put(PARAMETERS, jsonObject); + } + for (Map.Entry objParameter : operation.getObjectParams().entrySet()) { + jsonObject.put(objParameter.getKey(), JsonConverter.toJSON(objParameter.getValue())); + } + } params.add(query); eventBean.setParameters(params); if (operation.isStoredProcedureCall()) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index 3e4fac1cf..70f62c855 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -406,7 +406,7 @@ private static void processStackTrace(AbstractOperation operation) { AgentMetaData metaData = NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData(); if (stackTrace[i - 1].getLineNumber() > 0 && StringUtils.isNotBlank(stackTrace[i - 1].getFileName()) && - !StringUtils.startsWithAny(stackTrace[i - 1].getClassName(), "com.newrelic.", "com.nr.") + !StringUtils.startsWithAny(stackTrace[i - 1].getClassName(), "com.newrelic.agent.security.", "com.newrelic.api.agent.") ) { metaData.setTriggerViaRCI(true); metaData.getRciMethodsCalls() diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java index 751f4d24f..20bc93d09 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java @@ -49,8 +49,8 @@ public AgentMetaData() { } public AgentMetaData(AgentMetaData agentMetaData) { - this.rciMethodsCalls = new HashSet<>(); - this.rciMethodsCalls.addAll(agentMetaData.rciMethodsCalls); + agentMetaData.rciMethodsCalls.remove(null); + this.rciMethodsCalls = new HashSet<>(agentMetaData.rciMethodsCalls); this.triggerViaDeserialisation = agentMetaData.triggerViaDeserialisation; this.triggerViaRCI = agentMetaData.triggerViaRCI; this.isClientDetectedFromXFF = agentMetaData.isClientDetectedFromXFF; diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java index aab96090d..54d7e807b 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java @@ -14,6 +14,8 @@ public class SQLOperation extends AbstractOperation { private Map params; + private Map objectParams; + private String dbName = "UNKNOWN"; private boolean isPreparedCall; @@ -24,6 +26,7 @@ public SQLOperation(String className, String methodName) { this.setCaseType(VulnerabilityCaseType.SQL_DB_COMMAND); this.query = EMPTY; this.params = new HashMap<>(); + this.objectParams = new HashMap<>(); } public String getQuery() { @@ -54,7 +57,7 @@ public void setPreparedCall(boolean preparedCall) { public boolean isEmpty() { if (query == null || query.trim().isEmpty()) { return true; - } else if (isPreparedCall) { + } else if (isPreparedCall && params != null) { return query.contains("?") && params.isEmpty(); } return false; @@ -82,6 +85,14 @@ public String getDbName() { return dbName; } + public Map getObjectParams() { + return objectParams; + } + + public void setObjectParams(Map objectParams) { + this.objectParams = objectParams; + } + /** * @param dbName the dbName to set */ From a4d7b5a80ca7f2efdf56ea9b8915fb2e7858cf95 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 15 Mar 2024 16:56:20 +0530 Subject: [PATCH 065/124] NR-234900 : Add instrumentation to remaining setters of PreparedStatement Co-authored-by: Lovesh Baya --- .../PreparedStatement_Instrumentation.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java b/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java index a6af2b84b..b78888973 100644 --- a/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java +++ b/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java @@ -23,6 +23,7 @@ import java.math.BigDecimal; import java.net.URL; +import java.util.Calendar; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; @@ -259,6 +260,26 @@ public void setArray (int parameterIndex, Array x) throws SQLException { setObjectParams(parameterIndex, x.getArray()); Weaver.callOriginal(); } + public void setDate(int parameterIndex, java.sql.Date x, Calendar cal) throws SQLException { + setParamValue(parameterIndex, x); + Weaver.callOriginal(); + } + public void setTime(int parameterIndex, java.sql.Time x, Calendar cal) throws SQLException { + setParamValue(parameterIndex, x); + Weaver.callOriginal(); + } + public void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal) throws SQLException { + setParamValue(parameterIndex, x); + Weaver.callOriginal(); + } + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + setParamValue(parameterIndex, "null"); + Weaver.callOriginal(); + } + public void setNString(int parameterIndex, String value) throws SQLException { + setParamValue(parameterIndex, value); + Weaver.callOriginal(); + } public void setObject(int parameterIndex, Object x) throws SQLException { if(x instanceof Long || x instanceof Integer || x instanceof Double || @@ -277,6 +298,71 @@ public void setObject(int parameterIndex, Object x) throws SQLException { Weaver.callOriginal(); } + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { + if(x instanceof Long || x instanceof Integer || x instanceof Double || + x instanceof Float || x instanceof Boolean || x instanceof Short || + x instanceof String || x instanceof byte[] || x instanceof Timestamp || + x instanceof Date || x instanceof BigDecimal || x instanceof Time) { + setParamValue(parameterIndex, x); + } else if (x instanceof SQLXML) { + setParamValue(parameterIndex, ((SQLXML) x).getString()); + } else if (x instanceof RowId || x instanceof URL) { + setParamValue(parameterIndex, x.toString()); + } else { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); + setObjectParams(parameterIndex, x); + } + Weaver.callOriginal(); + } + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { + if(x instanceof Long || x instanceof Integer || x instanceof Double || + x instanceof Float || x instanceof Boolean || x instanceof Short || + x instanceof String || x instanceof byte[] || x instanceof Timestamp || + x instanceof Date || x instanceof BigDecimal || x instanceof Time) { + setParamValue(parameterIndex, x); + } else if (x instanceof SQLXML) { + setParamValue(parameterIndex, ((SQLXML) x).getString()); + } else if (x instanceof RowId || x instanceof URL) { + setParamValue(parameterIndex, x.toString()); + } else { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); + setObjectParams(parameterIndex, x); + } + Weaver.callOriginal(); + } + public void setObject(int parameterIndex, Object x, SQLType targetSqlType) throws SQLException { + if(x instanceof Long || x instanceof Integer || x instanceof Double || + x instanceof Float || x instanceof Boolean || x instanceof Short || + x instanceof String || x instanceof byte[] || x instanceof Timestamp || + x instanceof Date || x instanceof BigDecimal || x instanceof Time) { + setParamValue(parameterIndex, x); + } else if (x instanceof SQLXML) { + setParamValue(parameterIndex, ((SQLXML) x).getString()); + } else if (x instanceof RowId || x instanceof URL) { + setParamValue(parameterIndex, x.toString()); + } else { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); + setObjectParams(parameterIndex, x); + } + Weaver.callOriginal(); + } + public void setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { + if(x instanceof Long || x instanceof Integer || x instanceof Double || + x instanceof Float || x instanceof Boolean || x instanceof Short || + x instanceof String || x instanceof byte[] || x instanceof Timestamp || + x instanceof Date || x instanceof BigDecimal || x instanceof Time) { + setParamValue(parameterIndex, x); + } else if (x instanceof SQLXML) { + setParamValue(parameterIndex, ((SQLXML) x).getString()); + } else if (x instanceof RowId || x instanceof URL) { + setParamValue(parameterIndex, x.toString()); + } else { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); + setObjectParams(parameterIndex, x); + } + Weaver.callOriginal(); + } + public void clearParameters() throws SQLException { if(params != null){ params.clear(); From b3edf93c8d747cbb2ab0e39463ba06f9660d9b5d Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 18 Mar 2024 15:12:01 +0530 Subject: [PATCH 066/124] Add reason to critical logging for fuzz fail request --- .../instrumentator/httpclient/RestClient.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java index f39be870c..f47245526 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java @@ -25,7 +25,7 @@ public class RestClient { public static final String REQUEST_FIRED_SUCCESS = "Request Fired successfuly : %s "; public static final String REQUEST_SUCCESS_S_RESPONSE_S_S = "Request Fired successfuly : %s :: response : %s : %s"; - public static final String CALL_FAILED_REQUEST_S_REASON = "Call failed : request %s reason : "; + public static final String CALL_FAILED_REQUEST_S_REASON = "Call failed : request %s reason : %s "; public static final String CALL_FAILED_REQUEST_S_REASON_S = "Call failed : request %s reason : %s : body : %s"; public static final String FIRING_REQUEST_METHOD_S = "Firing request :: Method : %s"; @@ -130,9 +130,9 @@ public void fireRequest(FuzzRequestBean httpRequest, List endpoints, int try { responseCode = RestClient.getInstance().fireRequest(request, repeatCount + endpoints.size() -1, fuzzRequestId); } catch (SSLException e) { - logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, request), e, RestClient.class.getName()); + logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, request, e.getMessage()), e, RestClient.class.getName()); logger.postLogMessageIfNecessary(LogLevel.WARNING, - String.format(CALL_FAILED_REQUEST_S_REASON, fuzzRequestId), + String.format(CALL_FAILED_REQUEST_S_REASON, fuzzRequestId, e.getMessage()), e, RestRequestProcessor.class.getName()); RestRequestThreadPool.getInstance().getProcessedIds().putIfAbsent(fuzzRequestId, new HashSet<>()); // TODO: Add to fuzz fail count in HC and remove FuzzFailEvent if not needed. @@ -152,7 +152,7 @@ public void fireRequest(FuzzRequestBean httpRequest, List endpoints, int if(responseCode == 301){continue;} break; } catch (SSLException e){ - logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, request), e, RestClient.class.getName()); + logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, e.getMessage(), request), e, RestClient.class.getName()); } } @@ -186,16 +186,16 @@ public int fireRequest(Request request, int repeatCount, String fuzzRequestId) t } return response.code(); } catch (SSLException e){ - logger.log(LogLevel.FINE, String.format("Request failed due to SSL Exception %s ", request, e), RestClient.class.getName()); + logger.log(LogLevel.FINE, String.format("Request failed due to SSL Exception %s : reason %s", request, e.getMessage()), e, RestClient.class.getName()); throw e; } catch (InterruptedIOException e){ if(repeatCount >= 0){ return fireRequest(request, --repeatCount, fuzzRequestId); } } catch (IOException e) { - logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, request), e, RestClient.class.getName()); + logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, e.getMessage(), request), e, RestClient.class.getName()); logger.postLogMessageIfNecessary(LogLevel.WARNING, - String.format(CALL_FAILED_REQUEST_S_REASON, fuzzRequestId), + String.format(CALL_FAILED_REQUEST_S_REASON, e.getMessage(), fuzzRequestId), e, RestRequestProcessor.class.getName()); RestRequestThreadPool.getInstance().getProcessedIds().putIfAbsent(fuzzRequestId, new HashSet<>()); // TODO: Add to fuzz fail count in HC and remove FuzzFailEvent if not needed. From a8133ef6cfd0f87dd585cec6321fc74de54c008c Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 19 Mar 2024 15:10:57 +0530 Subject: [PATCH 067/124] NR-234880 : Revamp user class deetction technique by the help of API Handlers detected Co-authored-by: idawda --- .../newrelic/api/agent/security/Agent.java | 29 +++++++++++++++---- .../helpers/URLMappingsHelper.java | 8 +++++ .../schema/ApplicationURLMapping.java | 10 +++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index 59956c3f3..7629dceb0 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -9,6 +9,8 @@ import com.newrelic.agent.security.intcodeagent.constants.AgentServices; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.filelogging.LogFileHelper; +import com.newrelic.agent.security.intcodeagent.utils.EncryptorUtils; +import com.newrelic.api.agent.security.instrumentation.helpers.*; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.logging.HealthCheckScheduleThread; import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; @@ -21,10 +23,6 @@ import com.newrelic.agent.security.util.IUtilConstants; import com.newrelic.api.agent.NewRelic; import com.newrelic.api.agent.Transaction; -import com.newrelic.api.agent.security.instrumentation.helpers.GrpcHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.AppServerInfoHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.InstrumentedClass; -import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.schema.*; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; @@ -370,12 +368,22 @@ private UserClassEntity setUserClassEntity(AbstractOperation operation, Security for (int i = 0; i < operation.getStackTrace().length; i++) { StackTraceElement stackTraceElement = operation.getStackTrace()[i]; + + // Section for user class identification using API handlers + if( !securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod() && URLMappingsHelper.getHandlersHash().contains(operation.getClassName().hashCode())){ + //Found -> assign user class and return + userClassEntity.setUserClassElement(stackTraceElement); + securityMetaData.getMetaData().setUserLevelServiceMethodEncountered(true); + userClassEntity.setCalledByUserCode(true); + } + + //Fallback to old mechanism if(userStackTraceElement != null){ if(StringUtils.equals(stackTraceElement.getClassName(), userStackTraceElement.getClassName()) && StringUtils.equals(stackTraceElement.getMethodName(), userStackTraceElement.getMethodName())){ userClassEntity.setUserClassElement(stackTraceElement); userClassEntity.setCalledByUserCode(securityMetaData.getMetaData().isUserLevelServiceMethodEncountered()); - return userClassEntity; + userStackTraceElement = stackTraceElement; } } // TODO: the `if` should be `else if` please check crypto case BenchmarkTest01978. service trace is being registered from doSomething() @@ -684,4 +692,15 @@ public void retransformUninstrumentedClass(Class classToRetransform) { NewRelic.getAgent().getLogger().log(Level.FINER, "Class ", classToRetransform, " already instrumented."); } } + + @Override + public String decryptAndVerify(String encryptedData, String hashVerifier) { + String decryptedData = EncryptorUtils.decrypt(AgentInfo.getInstance().getLinkingMetadata().get(INRSettingsKey.NR_ENTITY_GUID), encryptedData); + if(EncryptorUtils.verifyHashData(hashVerifier, decryptedData)) { + return decryptedData; + } else { + NewRelic.getAgent().getLogger().log(Level.WARNING, String.format("Agent data decryption verifier fails on data : %s hash : %s", encryptedData, hashVerifier), Agent.class.getName()); + return null; + } + } } \ No newline at end of file diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java index 4e5f5df4c..1a2a36205 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java @@ -12,7 +12,15 @@ public static Set getApplicationURLMappings() { return mappings; } + private static Set handlers = ConcurrentHashMap.newKeySet(); + + public static Set getHandlersHash() { + return handlers; + } + public static void addApplicationURLMapping(ApplicationURLMapping mapping) { + mapping.setHandlerHash(mapping.getHandler().hashCode()); mappings.add(mapping); + handlers.add(mapping.getHandler().hashCode()); } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java index 8b48ab5da..4f1b884f7 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java @@ -7,6 +7,8 @@ public class ApplicationURLMapping { private String path; private String handler; + private int handlerHash; + public ApplicationURLMapping(String method, String url) { this.method = method; this.path = url; @@ -42,6 +44,14 @@ public void setPath(String path) { this.path = path; } + public int getHandlerHash() { + return handlerHash; + } + + public void setHandlerHash(int handlerHash) { + this.handlerHash = handlerHash; + } + @Override public boolean equals(Object obj) { if (obj == this) { From 6c82a9c361286078790e4dcaa13188f81e2edcb8 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 19 Mar 2024 17:09:51 +0530 Subject: [PATCH 068/124] add null checks to ApplicationURLMapping Co-authored-by: Lovesh Baya --- .../security/instrumentation/helpers/URLMappingsHelper.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java index 1a2a36205..4b3b01200 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java @@ -19,8 +19,10 @@ public static Set getHandlersHash() { } public static void addApplicationURLMapping(ApplicationURLMapping mapping) { - mapping.setHandlerHash(mapping.getHandler().hashCode()); + if (mapping.getHandler() != null){ + mapping.setHandlerHash(mapping.getHandler().hashCode()); + handlers.add(mapping.getHandler().hashCode()); + } mappings.add(mapping); - handlers.add(mapping.getHandler().hashCode()); } } From 02a44f6e42cf5085bb929b7a33f136e5431bb24e Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 19 Mar 2024 17:11:06 +0530 Subject: [PATCH 069/124] fix checks for user class detection using API endpoint handlers Co-authored-by: Lovesh Baya --- .../src/main/java/com/newrelic/api/agent/security/Agent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index 7629dceb0..b822a7eba 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -370,11 +370,12 @@ private UserClassEntity setUserClassEntity(AbstractOperation operation, Security StackTraceElement stackTraceElement = operation.getStackTrace()[i]; // Section for user class identification using API handlers - if( !securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod() && URLMappingsHelper.getHandlersHash().contains(operation.getClassName().hashCode())){ + if( !securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod() && URLMappingsHelper.getHandlersHash().contains(stackTraceElement.getClassName().hashCode())){ //Found -> assign user class and return userClassEntity.setUserClassElement(stackTraceElement); securityMetaData.getMetaData().setUserLevelServiceMethodEncountered(true); userClassEntity.setCalledByUserCode(true); + return userClassEntity; } //Fallback to old mechanism From 8a090bc082a8821737c73ef71544d1dac3d5508a Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 20 Mar 2024 09:53:09 +0530 Subject: [PATCH 070/124] add annotated UserLevelService Method true for jax-rs --- .../javax/ws/rs/api/JavaxWsRsApi_Instrumentation.java | 1 + .../ws/rs/api/JavaxWsRsApi_Subresource_Instrumentation.java | 1 + .../jakarta/ws/rs/api/JakartaWsRsApi_Instrumentation.java | 1 + .../ws/rs/api/JakartaWsRsApi_Subresource_Instrumentation.java | 1 + 4 files changed, 4 insertions(+) diff --git a/instrumentation-security/jax-rs-1.0/src/main/java/com/newrelic/agent/security/instrumentation/javax/ws/rs/api/JavaxWsRsApi_Instrumentation.java b/instrumentation-security/jax-rs-1.0/src/main/java/com/newrelic/agent/security/instrumentation/javax/ws/rs/api/JavaxWsRsApi_Instrumentation.java index b7211b1af..c18d2c446 100644 --- a/instrumentation-security/jax-rs-1.0/src/main/java/com/newrelic/agent/security/instrumentation/javax/ws/rs/api/JavaxWsRsApi_Instrumentation.java +++ b/instrumentation-security/jax-rs-1.0/src/main/java/com/newrelic/agent/security/instrumentation/javax/ws/rs/api/JavaxWsRsApi_Instrumentation.java @@ -20,5 +20,6 @@ public class JavaxWsRsApi_Instrumentation { @WeaveIntoAllMethods public static void preprocessSecurityHook() { ServletHelper.registerUserLevelCode("jax-rs"); + ServletHelper.setFoundAnnotedUserLevelServiceMethod(); } } diff --git a/instrumentation-security/jax-rs-1.0/src/main/java/com/newrelic/agent/security/instrumentation/javax/ws/rs/api/JavaxWsRsApi_Subresource_Instrumentation.java b/instrumentation-security/jax-rs-1.0/src/main/java/com/newrelic/agent/security/instrumentation/javax/ws/rs/api/JavaxWsRsApi_Subresource_Instrumentation.java index 15018dfc2..b05be8a40 100644 --- a/instrumentation-security/jax-rs-1.0/src/main/java/com/newrelic/agent/security/instrumentation/javax/ws/rs/api/JavaxWsRsApi_Subresource_Instrumentation.java +++ b/instrumentation-security/jax-rs-1.0/src/main/java/com/newrelic/agent/security/instrumentation/javax/ws/rs/api/JavaxWsRsApi_Subresource_Instrumentation.java @@ -34,5 +34,6 @@ public class JavaxWsRsApi_Subresource_Instrumentation { @WeaveIntoAllMethods public static void preprocessSecurityHook() { ServletHelper.registerUserLevelCode("jax-rs"); + ServletHelper.setFoundAnnotedUserLevelServiceMethod(); } } diff --git a/instrumentation-security/jax-rs-3.0/src/main/java/com/newrelic/agent/security/instrumentation/jakarta/ws/rs/api/JakartaWsRsApi_Instrumentation.java b/instrumentation-security/jax-rs-3.0/src/main/java/com/newrelic/agent/security/instrumentation/jakarta/ws/rs/api/JakartaWsRsApi_Instrumentation.java index 1414c047f..d7f20c912 100644 --- a/instrumentation-security/jax-rs-3.0/src/main/java/com/newrelic/agent/security/instrumentation/jakarta/ws/rs/api/JakartaWsRsApi_Instrumentation.java +++ b/instrumentation-security/jax-rs-3.0/src/main/java/com/newrelic/agent/security/instrumentation/jakarta/ws/rs/api/JakartaWsRsApi_Instrumentation.java @@ -20,5 +20,6 @@ public class JakartaWsRsApi_Instrumentation { @WeaveIntoAllMethods public static void preprocessSecurityHook() { ServletHelper.registerUserLevelCode("jax-rs"); + ServletHelper.setFoundAnnotedUserLevelServiceMethod(); } } diff --git a/instrumentation-security/jax-rs-3.0/src/main/java/com/newrelic/agent/security/instrumentation/jakarta/ws/rs/api/JakartaWsRsApi_Subresource_Instrumentation.java b/instrumentation-security/jax-rs-3.0/src/main/java/com/newrelic/agent/security/instrumentation/jakarta/ws/rs/api/JakartaWsRsApi_Subresource_Instrumentation.java index 1b99cdf70..73f33dbbd 100644 --- a/instrumentation-security/jax-rs-3.0/src/main/java/com/newrelic/agent/security/instrumentation/jakarta/ws/rs/api/JakartaWsRsApi_Subresource_Instrumentation.java +++ b/instrumentation-security/jax-rs-3.0/src/main/java/com/newrelic/agent/security/instrumentation/jakarta/ws/rs/api/JakartaWsRsApi_Subresource_Instrumentation.java @@ -35,5 +35,6 @@ public class JakartaWsRsApi_Subresource_Instrumentation { @WeaveIntoAllMethods public static void preprocessSecurityHook() { ServletHelper.registerUserLevelCode("jax-rs"); + ServletHelper.setFoundAnnotedUserLevelServiceMethod(); } } From 99f3914a9847b8bd32ca64829e2e51cbe786746f Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 20 Mar 2024 09:54:55 +0530 Subject: [PATCH 071/124] updated Unit tests for spring and jax-rs support --- .../javax/ws/rs/api/test/JavaxWsRsApiTest.java | 8 ++++++++ .../javax/ws/rs/api/test/SubresourceTest.java | 8 ++++++++ .../jakarta/ws/rs/api/test/JakartaWsRsApiTest.java | 8 ++++++++ .../jakarta/ws/rs/api/test/SubresourceTest.java | 7 +++++++ .../springweb/springweb/test/SpringControllerTest.java | 6 ++++++ .../springweb/test/SpringRestControllerTest.java | 6 ++++++ 6 files changed, 43 insertions(+) diff --git a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java index 4146f3dff..d73b39901 100644 --- a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java +++ b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java @@ -21,6 +21,7 @@ public void testPut() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testPost() { @@ -31,6 +32,7 @@ public void testPost() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testGet() { @@ -41,6 +43,7 @@ public void testGet() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testDelete() { @@ -51,6 +54,7 @@ public void testDelete() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testHead() { @@ -60,6 +64,7 @@ public void testHead() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testOptions() { @@ -70,6 +75,7 @@ public void testOptions() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testPatch() { @@ -80,6 +86,7 @@ public void testPatch() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -91,5 +98,6 @@ public void testPath() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } } diff --git a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java index 61befaaf5..a67197b37 100644 --- a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java +++ b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java @@ -40,6 +40,7 @@ public void testPost() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -55,6 +56,7 @@ public void testPath() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -67,6 +69,7 @@ public void testGet() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -82,6 +85,7 @@ public void testPut() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -94,6 +98,7 @@ public void testDelete() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -106,6 +111,7 @@ public void testHead() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -118,6 +124,7 @@ public void testOptions() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testPatch() { @@ -131,6 +138,7 @@ public void testPatch() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } diff --git a/instrumentation-security/jax-rs-3.0/src/test/java/com/nr/agent/security/instrumentation/jakarta/ws/rs/api/test/JakartaWsRsApiTest.java b/instrumentation-security/jax-rs-3.0/src/test/java/com/nr/agent/security/instrumentation/jakarta/ws/rs/api/test/JakartaWsRsApiTest.java index 25d0b1eba..33eb00eee 100644 --- a/instrumentation-security/jax-rs-3.0/src/test/java/com/nr/agent/security/instrumentation/jakarta/ws/rs/api/test/JakartaWsRsApiTest.java +++ b/instrumentation-security/jax-rs-3.0/src/test/java/com/nr/agent/security/instrumentation/jakarta/ws/rs/api/test/JakartaWsRsApiTest.java @@ -21,6 +21,7 @@ public void testPut() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testPost() { @@ -31,6 +32,7 @@ public void testPost() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testGet() { @@ -41,6 +43,7 @@ public void testGet() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testDelete() { @@ -51,6 +54,7 @@ public void testDelete() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testHead() { @@ -61,6 +65,7 @@ public void testHead() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testOptions() { @@ -71,6 +76,7 @@ public void testOptions() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testPatch() { @@ -81,6 +87,7 @@ public void testPatch() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testPath() { @@ -91,5 +98,6 @@ public void testPath() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } } diff --git a/instrumentation-security/jax-rs-3.0/src/test/java/com/nr/agent/security/instrumentation/jakarta/ws/rs/api/test/SubresourceTest.java b/instrumentation-security/jax-rs-3.0/src/test/java/com/nr/agent/security/instrumentation/jakarta/ws/rs/api/test/SubresourceTest.java index 3fc39262e..23f9bbb01 100644 --- a/instrumentation-security/jax-rs-3.0/src/test/java/com/nr/agent/security/instrumentation/jakarta/ws/rs/api/test/SubresourceTest.java +++ b/instrumentation-security/jax-rs-3.0/src/test/java/com/nr/agent/security/instrumentation/jakarta/ws/rs/api/test/SubresourceTest.java @@ -40,6 +40,7 @@ public void testPost() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testPath() { @@ -54,6 +55,7 @@ public void testPath() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -66,6 +68,7 @@ public void testGet() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -81,6 +84,7 @@ public void testPut() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -105,6 +109,7 @@ public void testHead() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -117,6 +122,7 @@ public void testOptions() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test public void testPatch() { @@ -131,6 +137,7 @@ public void testPatch() { Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Override diff --git a/instrumentation-security/spring-web/src/test/java/com/nr/agent/security/instrumentation/springweb/springweb/test/SpringControllerTest.java b/instrumentation-security/spring-web/src/test/java/com/nr/agent/security/instrumentation/springweb/springweb/test/SpringControllerTest.java index 9a8038943..42c7fea30 100644 --- a/instrumentation-security/spring-web/src/test/java/com/nr/agent/security/instrumentation/springweb/springweb/test/SpringControllerTest.java +++ b/instrumentation-security/spring-web/src/test/java/com/nr/agent/security/instrumentation/springweb/springweb/test/SpringControllerTest.java @@ -31,6 +31,7 @@ public void testRequestMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -41,6 +42,7 @@ public void testGetMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -51,6 +53,7 @@ public void testPostMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -61,6 +64,7 @@ public void testPatchMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -71,6 +75,7 @@ public void testPutMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -81,5 +86,6 @@ public void testDeleteMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } } diff --git a/instrumentation-security/spring-web/src/test/java/com/nr/agent/security/instrumentation/springweb/springweb/test/SpringRestControllerTest.java b/instrumentation-security/spring-web/src/test/java/com/nr/agent/security/instrumentation/springweb/springweb/test/SpringRestControllerTest.java index ae4bfa3be..53a0686f8 100644 --- a/instrumentation-security/spring-web/src/test/java/com/nr/agent/security/instrumentation/springweb/springweb/test/SpringRestControllerTest.java +++ b/instrumentation-security/spring-web/src/test/java/com/nr/agent/security/instrumentation/springweb/springweb/test/SpringRestControllerTest.java @@ -30,6 +30,7 @@ public void testRequestMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -40,6 +41,7 @@ public void testGetMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -50,6 +52,7 @@ public void testPostMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -60,6 +63,7 @@ public void testPatchMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -70,6 +74,7 @@ public void testPutMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } @Test @@ -80,5 +85,6 @@ public void testDeleteMapping() { AgentMetaData meta = introspector.getSecurityMetaData().getMetaData(); Assert.assertNotNull("Service trace can not be empty/null.", meta.getServiceTrace()); Assert.assertTrue("user level service method was not encountered.", meta.isUserLevelServiceMethodEncountered()); + Assert.assertTrue("Annotated userLevelService Method was not encountered.", meta.isFoundAnnotedUserLevelServiceMethod()); } } From 226791c04a5675b335989b79a80b8d6183827b47 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 26 Mar 2024 14:44:37 +0530 Subject: [PATCH 072/124] Added Logging message constants for App Endpoint --- .../instrumentation/apache/tomcat10/HttpServletHelper.java | 7 +++---- .../instrumentation/apache/tomcat7/HttpServletHelper.java | 7 +++---- .../instrumentation/jetty11/HttpServletHelper.java | 6 ++---- .../security/instrumentation/jetty9/HttpServletHelper.java | 6 ++---- .../instrumentation/servlet24/HttpServletHelper.java | 6 ++---- .../instrumentation/servlet30/HttpServletHelper.java | 7 +++---- .../instrumentation/servlet6/HttpServletHelper.java | 6 ++---- .../security/instrumentation/helpers/GenericHelper.java | 1 + 8 files changed, 18 insertions(+), 28 deletions(-) diff --git a/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java b/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java index f118eb628..632f1c55d 100644 --- a/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java +++ b/instrumentation-security/apache-tomcat-10/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat10/HttpServletHelper.java @@ -1,6 +1,7 @@ package com.newrelic.agent.security.instrumentation.apache.tomcat10; import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -28,8 +29,7 @@ public static void gatherURLMappings(ServletContext servletContext) { } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, APACHE_TOMCAT_10, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, APACHE_TOMCAT_10, e.getMessage()), e, HttpServletHelper.class.getName()); } } @@ -47,8 +47,7 @@ else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, APACHE_TOMCAT_10, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, APACHE_TOMCAT_10, e.getMessage()), e, HttpServletHelper.class.getName()); } } } diff --git a/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java b/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java index 0822e64df..133a3112d 100644 --- a/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java +++ b/instrumentation-security/apache-tomcat-7/src/main/java/com/newrelic/agent/security/instrumentation/apache/tomcat7/HttpServletHelper.java @@ -1,6 +1,7 @@ package com.newrelic.agent.security.instrumentation.apache.tomcat7; import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -28,8 +29,7 @@ public static void gatherURLMappings(ServletContext servletContext) { } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, APACHE_TOMCAT_7, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, APACHE_TOMCAT_7, e.getMessage()), e, HttpServletHelper.class.getName()); } } @@ -47,8 +47,7 @@ else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, APACHE_TOMCAT_7, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, APACHE_TOMCAT_7, e.getMessage()), e, HttpServletHelper.class.getName()); } } } diff --git a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java index cb5cbd66a..4f69e8b6c 100644 --- a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java +++ b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java @@ -211,8 +211,7 @@ public static void gatherURLMappings(ServletContext servletContext) { } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, JETTY_11, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, JETTY_11, e.getMessage()), e, HttpServletHelper.class.getName()); } } @@ -230,8 +229,7 @@ else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, JETTY_11, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, JETTY_11, e.getMessage()), e, HttpServletHelper.class.getName()); } } } diff --git a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java index 457ac48bd..24c5b34c1 100644 --- a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java +++ b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java @@ -213,8 +213,7 @@ public static void gatherURLMappings(ServletContext servletContext) { } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, JETTY_9, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, JETTY_9, e.getMessage()), e, HttpServletHelper.class.getName()); } } @@ -232,8 +231,7 @@ else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, JETTY_9, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, JETTY_9, e.getMessage()), e, HttpServletHelper.class.getName()); } } } diff --git a/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java b/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java index 754ff8f58..51dadf913 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java +++ b/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java @@ -130,8 +130,7 @@ public static void gatherURLMappings(ServletContext servletContext) { } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, SERVLET_2_4, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_2_4, e.getMessage()), e, HttpServletHelper.class.getName()); } } @@ -149,8 +148,7 @@ else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, SERVLET_2_4, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_2_4, e.getMessage()), e, HttpServletHelper.class.getName()); } } } diff --git a/instrumentation-security/servlet-3.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet30/HttpServletHelper.java b/instrumentation-security/servlet-3.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet30/HttpServletHelper.java index 805811544..5084a7634 100644 --- a/instrumentation-security/servlet-3.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet30/HttpServletHelper.java +++ b/instrumentation-security/servlet-3.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet30/HttpServletHelper.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -26,8 +27,7 @@ public static void gatherURLMappings(ServletContext servletContext) { } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, SERVLET_3_0, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_3_0, e.getMessage()), e, HttpServletHelper.class.getName()); } } @@ -45,8 +45,7 @@ else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, SERVLET_3_0, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_3_0, e.getMessage()), e, HttpServletHelper.class.getName()); } } } diff --git a/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java b/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java index c9ee8f79b..cd0132143 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java +++ b/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java @@ -130,8 +130,7 @@ public static void gatherURLMappings(ServletContext servletContext) { } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, SERVLET_6_0, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_6_0, e.getMessage()), e, HttpServletHelper.class.getName()); } } @@ -149,8 +148,7 @@ else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") } } } catch (Exception e){ - String message = "Instrumentation library: %s , error while getting app endpoints : %s"; - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, SERVLET_6_0, e.getMessage()), e, HttpServletHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_6_0, e.getMessage()), e, HttpServletHelper.class.getName()); } } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java index 4a5e28067..2d027486d 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GenericHelper.java @@ -18,6 +18,7 @@ public class GenericHelper { public static final String URI_EXCEPTION_MESSAGE = "Instrumentation library: %s , error while extracting URI : %s"; public static final String ERROR_GENERATING_HTTP_REQUEST = "Instrumentation library: %s , error while generating HTTP request : %s"; public static final String ERROR_PARSING_HTTP_REQUEST_DATA = "Instrumentation library: %s , error while parsing HTTP request data : %s"; + public static final String ERROR_WHILE_GETTING_APP_ENDPOINTS = "Instrumentation library: %s , error while getting application API endpoints : %s"; public static boolean skipExistsEvent() { if (!(NewRelicSecurity.getAgent().getCurrentPolicy().getVulnerabilityScan().getEnabled() && From b615bcbf61eac952a7dd800de78e45df1be5404b Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 28 Mar 2024 12:33:11 +0530 Subject: [PATCH 073/124] Cleanup : removed unused POJO elemnts --- .../java/com/newrelic/api/agent/security/Agent.java | 11 ----------- .../instrumentation/helpers/URLMappingsHelper.java | 1 - .../agent/security/schema/ApplicationURLMapping.java | 10 ---------- 3 files changed, 22 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index b822a7eba..66737b694 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -9,7 +9,6 @@ import com.newrelic.agent.security.intcodeagent.constants.AgentServices; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.filelogging.LogFileHelper; -import com.newrelic.agent.security.intcodeagent.utils.EncryptorUtils; import com.newrelic.api.agent.security.instrumentation.helpers.*; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.logging.HealthCheckScheduleThread; @@ -694,14 +693,4 @@ public void retransformUninstrumentedClass(Class classToRetransform) { } } - @Override - public String decryptAndVerify(String encryptedData, String hashVerifier) { - String decryptedData = EncryptorUtils.decrypt(AgentInfo.getInstance().getLinkingMetadata().get(INRSettingsKey.NR_ENTITY_GUID), encryptedData); - if(EncryptorUtils.verifyHashData(hashVerifier, decryptedData)) { - return decryptedData; - } else { - NewRelic.getAgent().getLogger().log(Level.WARNING, String.format("Agent data decryption verifier fails on data : %s hash : %s", encryptedData, hashVerifier), Agent.class.getName()); - return null; - } - } } \ No newline at end of file diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java index 4b3b01200..2db83cf14 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java @@ -20,7 +20,6 @@ public static Set getHandlersHash() { public static void addApplicationURLMapping(ApplicationURLMapping mapping) { if (mapping.getHandler() != null){ - mapping.setHandlerHash(mapping.getHandler().hashCode()); handlers.add(mapping.getHandler().hashCode()); } mappings.add(mapping); diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java index 4f1b884f7..8b48ab5da 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java @@ -7,8 +7,6 @@ public class ApplicationURLMapping { private String path; private String handler; - private int handlerHash; - public ApplicationURLMapping(String method, String url) { this.method = method; this.path = url; @@ -44,14 +42,6 @@ public void setPath(String path) { this.path = path; } - public int getHandlerHash() { - return handlerHash; - } - - public void setHandlerHash(int handlerHash) { - this.handlerHash = handlerHash; - } - @Override public boolean equals(Object obj) { if (obj == this) { From 33353f67edb262a7c323bea25632a779fde9f30b Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Thu, 28 Mar 2024 18:32:43 +0530 Subject: [PATCH 074/124] Fix for NR-234411 (#206) * Fix for NPE in API Endpoint Support --- gradle.properties | 1 + .../api/agent/security/schema/ApplicationURLMapping.java | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 765ec9338..7e11bbbdc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,5 @@ # The agent version. + agentVersion=1.1.2 jsonVersion=1.1.1 # Updated exposed NR APM API version. diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java index 8b48ab5da..74912886b 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ApplicationURLMapping.java @@ -47,10 +47,11 @@ public boolean equals(Object obj) { if (obj == this) { return true; } - if (obj instanceof ApplicationURLMapping) { ApplicationURLMapping mapping = (ApplicationURLMapping) obj; - return path.equals(mapping.path) && method.equals(mapping.method) && handler.equals(mapping.handler); + return Objects.equals(this.path, mapping.path) && + Objects.equals(this.method, mapping.method) && + Objects.equals(this.handler, mapping.handler); } return false; } From 0e839fe392d80ba48c2fcb6dee70208da2804d7f Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Thu, 28 Mar 2024 18:33:32 +0530 Subject: [PATCH 075/124] Fix for NR-234390 (#208) Removed default framework handlers from endpoint list --- .../instrumentation/helpers/URLMappingsHelper.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java index 4e5f5df4c..7a58d1fe8 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java @@ -2,17 +2,28 @@ import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class URLMappingsHelper { private static Set mappings = ConcurrentHashMap.newKeySet(); + private static final Set defaultHandlers = new HashSet() {{ + add("org.eclipse.jetty.jsp.JettyJspServlet"); + add("org.eclipse.jetty.servlet.ServletHandler$Default404Servlet"); + add("org.glassfish.jersey.servlet.ServletContainer"); + add("org.apache.jasper.servlet.JspServlet"); + add("org.apache.catalina.servlets.DefaultServlet"); + add("org.eclipse.jetty.servlet.DefaultServlet"); + }}; public static Set getApplicationURLMappings() { return mappings; } public static void addApplicationURLMapping(ApplicationURLMapping mapping) { - mappings.add(mapping); + if (mapping.getHandler() == null || (mapping.getHandler() != null && !defaultHandlers.contains(mapping.getHandler()))) { + mappings.add(mapping); + } } } From 3f306913f9f28d357d45f1365546649b58d0d9a8 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 29 Mar 2024 16:58:47 +0530 Subject: [PATCH 076/124] Add more UTs to netty support --- .../instrumentation/netty400/NettyServer.java | 82 ++++++++++++++++ .../instrumentation/netty400/NettyTest.java | 93 +++++++++++++------ 2 files changed, 147 insertions(+), 28 deletions(-) create mode 100644 instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyServer.java diff --git a/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyServer.java b/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyServer.java new file mode 100644 index 000000000..ea7a623be --- /dev/null +++ b/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyServer.java @@ -0,0 +1,82 @@ +package com.nr.agent.security.instrumentation.netty400; + +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.util.CharsetUtil; +import org.junit.rules.ExternalResource; + +import java.net.MalformedURLException; +import java.net.URL; + +public class NettyServer extends ExternalResource { + private Channel channel; + private int PORT; + + @Override + protected void before() throws Throwable { + PORT = SecurityInstrumentationTestRunner.getIntrospector().getRandomPort(); + startServer(); + } + + @Override + protected void after() { + stopServer(); + } + private void startServer() throws InterruptedException { + ServerBootstrap b = new ServerBootstrap(); + b.group(new NioEventLoopGroup(),new NioEventLoopGroup()) + .channel(NioServerSocketChannel.class) + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(Channel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast(new HttpServerCodec()); + pipeline.addLast(new HttpObjectAggregator(65536)); + pipeline.addLast(new SimpleChannelInboundHandler() { + @Override + protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest o) throws Exception { + o.content(); + FullHttpResponse response = new DefaultFullHttpResponse( + HttpVersion.HTTP_1_0, + HttpResponseStatus.OK, + Unpooled.copiedBuffer("write data", CharsetUtil.UTF_8)); + HttpHeaders.addHeader(response, HttpHeaders.Names.CONTENT_TYPE, "text/html"); + ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + } + }); + } + }); + + channel = b.bind(PORT).sync().channel(); + System.out.println("checking..."); + } + + private void stopServer(){ + if (channel.isActive() && channel.isOpen()){ + channel.close(); + } + } + public URL getEndPoint() throws MalformedURLException { + return new URL("http://localhost:" + PORT + "/"); + } +} diff --git a/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java b/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java index 4ceabeb60..d04b4b722 100644 --- a/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java +++ b/instrumentation-security/netty-4.0.8/src/test/java/com/nr/agent/security/instrumentation/netty400/NettyTest.java @@ -27,84 +27,109 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import org.junit.Assert; +import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import security.io.netty400.utils.NettyUtils; +import java.io.IOException; +import java.net.HttpURLConnection; import java.util.List; @RunWith(SecurityInstrumentationTestRunner.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @InstrumentationTestConfig(includePrefixes = {"security.io.netty400"}) public class NettyTest { + @ClassRule + public static NettyServer server = new NettyServer(); + + private final String header = "text/html"; @Test - public void testChannelRead() throws JsonProcessingException { + public void testChannelRXSS() throws IOException { + connect(); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertFalse("No operations detected", operations.isEmpty()); + + RXSSOperation operation = (RXSSOperation) operations.get(0); + Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); + Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); + + HttpResponse response = introspector.getSecurityMetaData().getResponse(); + Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid response body", "write data", response.getResponseBody().toString()); + } + @Test + public void testChannelRead() { channelRead(); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("Operations detected", operations.size() == 0); + Assert.assertTrue("Operations detected", operations.isEmpty()); + HttpRequest request = introspector.getSecurityMetaData().getRequest(); - Assert.assertEquals("Invalid protocol", "HTTP", request.getProtocol()); + Assert.assertEquals("Invalid protocol", "http", request.getProtocol()); Assert.assertNotNull("No URL", request.getUrl()); - Assert.assertEquals("Invalid content-type", "text/html", request.getContentType()); - Assert.assertEquals("Invalid headers", "text/html", request.getHeaders().get("content-type")); - Assert.assertEquals("Invalid response body", "read data", request.getBody().toString()); + Assert.assertEquals("Invalid content-type", header, request.getContentType()); + Assert.assertEquals("Invalid headers", header, request.getHeaders().get("content-type")); + Assert.assertEquals("Invalid request body", "read data", request.getBody().toString()); } @Test - public void testWrite() throws JsonProcessingException { + public void testWrite() { write(); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); + Assert.assertFalse("No operations detected", operations.isEmpty()); RXSSOperation operation = (RXSSOperation) operations.get(0); Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); HttpResponse response = introspector.getSecurityMetaData().getResponse(); - Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); - Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); Assert.assertEquals("Invalid response body", "write data", response.getResponseBody().toString()); } @Test - public void testWriteAndFlush() throws JsonProcessingException { + public void testWriteAndFlush() { writeAndFlush(); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); + Assert.assertFalse("No operations detected", operations.isEmpty()); RXSSOperation operation = (RXSSOperation) operations.get(0); Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); HttpResponse response = introspector.getSecurityMetaData().getResponse(); - Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); - Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); Assert.assertEquals("Invalid response body", "write flush data", response.getResponseBody().toString()); } @Test - public void testWriteAndFlushPromise() throws JsonProcessingException { + public void testWriteAndFlushPromise() { writeAndFlushPromise(); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); + Assert.assertFalse("No operations detected", operations.isEmpty()); RXSSOperation operation = (RXSSOperation) operations.get(0); Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); HttpResponse response = introspector.getSecurityMetaData().getResponse(); - Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); - Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); Assert.assertEquals("Invalid response body", "write flush promise data", response.getResponseBody().toString()); } @@ -114,24 +139,25 @@ public void testEncode() { SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); + Assert.assertFalse("No operations detected", operations.isEmpty()); RXSSOperation operation = (RXSSOperation) operations.get(0); Assert.assertEquals("Invalid executed method name", NettyUtils.WRITE_METHOD_NAME, operation.getMethodName()); Assert.assertEquals("Invalid event category", VulnerabilityCaseType.REFLECTED_XSS, operation.getCaseType()); HttpResponse response = introspector.getSecurityMetaData().getResponse(); - Assert.assertEquals("Invalid content-type body", "text/html", response.getResponseContentType()); - Assert.assertEquals("Invalid content-type body", "text/html", response.getHeaders().get("content-type")); + Assert.assertEquals("Invalid content-type body", header, response.getResponseContentType()); + Assert.assertEquals("Invalid content-type body", header, response.getHeaders().get("content-type")); Assert.assertEquals("Invalid response body", "encode data", response.getResponseBody().toString()); } @Trace(dispatcher = true) private void channelRead() { EmbeddedChannel channel = new EmbeddedChannel(new ChannelInboundHandlerAdapter()); - FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, "/test"); - httpRequest.headers().add("content-type", "text/html"); + FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.POST, "/test"); + httpRequest.headers().add("content-type", header); DefaultHttpContent httpContent = new DefaultHttpContent(Unpooled.wrappedBuffer("read data".getBytes())); +// httpRequest.content().writeBytes("read data".getBytes()); channel.writeInbound(httpRequest, httpContent); channel.read(); } @@ -140,7 +166,7 @@ private void channelRead() { private void write() { EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); - response.headers().add("content-type","text/html"); + response.headers().add("content-type", header); response.content().writeBytes("write data".getBytes()); channel.write(response); @@ -151,7 +177,7 @@ private void write() { private void writeAndFlush() { EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); - response.headers().add("content-type","text/html"); + response.headers().add("content-type", header); response.content().writeBytes("write flush data".getBytes()); channel.writeAndFlush(response); @@ -161,7 +187,7 @@ private void writeAndFlush() { private void writeAndFlushPromise() { EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); - response.headers().add("content-type","text/html"); + response.headers().add("content-type", header); response.content().writeBytes("write flush promise data".getBytes()); channel.writeAndFlush(response, channel.newPromise()); @@ -171,11 +197,22 @@ private void writeAndFlushPromise() { private void encode() { EmbeddedChannel channel = new EmbeddedChannel(new ChannelOutboundHandlerAdapter()); channel.pipeline().addLast(new HttpResponseEncoder()); - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.ACCEPTED); - response.headers().add("content-type","text/html"); + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.ACCEPTED); + response.headers().add("content-type", header); response.content().writeBytes("encode data".getBytes()); channel.write(response); channel.flush(); } + @Trace(dispatcher = true) + private void connect() throws IOException { + HttpURLConnection connection = (HttpURLConnection) server.getEndPoint().openConnection(); + connection.setDoOutput(true); + connection.setRequestMethod("POST"); + connection.setRequestProperty("content-type", header); + connection.getOutputStream().write("name=ishi".getBytes()); + + connection.connect(); + System.out.println(connection.getResponseCode()); + } } \ No newline at end of file From a0f1d15abaac426f499572a9d893d455c37388af Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 29 Mar 2024 17:06:47 +0530 Subject: [PATCH 077/124] Enabled jCache support --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index df0e06951..42e59a461 100644 --- a/settings.gradle +++ b/settings.gradle @@ -172,7 +172,7 @@ include 'instrumentation:jersey-2' include 'instrumentation:jersey-2.16' include 'instrumentation:jersey-3' include 'instrumentation:spring-data-redis' -//include 'instrumentation:jcache-1.0.0' +include 'instrumentation:jcache-1.0.0' include 'instrumentation:lettuce-4.3' include 'instrumentation:lettuce-5.0' //include 'instrumentation:spymemcached-2.12.0' From baf5a015a715a8f23cc66d9582f1509cd925472b Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 1 Apr 2024 12:56:42 +0530 Subject: [PATCH 078/124] Exclude milestore release for JAX RX Fix Verifier for new release on 29March 4.0.0-M2 --- instrumentation-security/jax-rs-3.0/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation-security/jax-rs-3.0/build.gradle b/instrumentation-security/jax-rs-3.0/build.gradle index 34040fc01..6a2e0b44b 100644 --- a/instrumentation-security/jax-rs-3.0/build.gradle +++ b/instrumentation-security/jax-rs-3.0/build.gradle @@ -19,6 +19,7 @@ jar { verifyInstrumentation { passesOnly 'jakarta.ws.rs:jakarta.ws.rs-api:[3.0-M1,)' + excludeRegex '.*-M[0-9]+' } compileJava { From b9f295cadefd82e453c43e79e8d5ab09cbbc4a1a Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 1 Apr 2024 13:11:45 +0530 Subject: [PATCH 079/124] CSEC version bump to 1.2.1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4fa7e073f..1515da4a9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # The agent version. -agentVersion=1.2.0 +agentVersion=1.2.1 jsonVersion=1.2.0 # Updated exposed NR APM API version. nrAPIVersion=8.4.0 From feae0afd6cbdfbab8ea2119e6be5bd026f020d0c Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Tue, 2 Apr 2024 11:31:58 +0530 Subject: [PATCH 080/124] Fix unit tests (#224) * Add unit tests for IAST replay header decryption * Fix failure of Unit Tests For Java version 17 * Fix API Endpoint Unit Tests Co-authored-by: Lovesh Baya --- .../akka/http/core_10/AkkaHttpCoreTest.scala | 31 +++++- .../akka/http/core_10/AkkaHttpCoreTest.scala | 32 +++++- .../akka/http/core_10/AkkaHttpCoreTest.scala | 31 +++++- .../tomcat10/APIEndpointTest.java | 5 +- .../tomcat7/APIEndpointTest.java | 5 +- .../instrumentation/grpc1220/GrpcTest.java | 55 +++++++-- .../instrumentation/grpc140/GrpcTest.java | 55 +++++++-- .../instrumentation/grpc1400/GrpcTest.java | 56 ++++++++-- .../javax/jndi/ContextRmiTest.java | 3 + .../javax/jndi/ContextTest.java | 3 + .../javax/ldap/DirContextTest.java | 3 + .../ws/rs/api/test/JavaxWsRsApiTest.java | 3 + .../javax/ws/rs/api/test/SubresourceTest.java | 3 + .../xpath/jaxen/BaseXPathTest.java | 3 + .../xpath/jaxen/BaseXPathTest.java | 3 + .../postgresql80312/DataStoreTest.java | 3 +- .../postgresql80312/DriverTest.java | 3 +- .../postgresql80312/PgStatementTest.java | 3 +- .../postgresql941207/DataStoreTest.java | 3 +- .../postgresql941207/DriverTest.java | 3 +- .../postgresql941207/PgStatementTest.java | 3 +- .../postgresql941208/DataStoreTest.java | 3 +- .../postgresql941208/DriverTest.java | 3 +- .../instrumentation/jersey2/JerseyTests.java | 6 +- .../instrumentation/jersey2/JerseyTests.java | 5 +- .../instrumentation/jersey2/JerseyTests.java | 6 +- .../instrumentation/jetty11/ServerTest.java | 99 ++++++++++++++--- .../jetty12/test/ServerTest.java | 39 ++++++- .../instrumentation/jetty9/ServerTest.java | 86 +++++++++++++++ .../jsp24/HttpJspPageTest.java | 3 + .../r2dbc/PostgresStatementTest.java | 3 + .../instrumentation/r2dbc/PostgresTest.java | 3 + .../servlet24/HttpServletTest.java | 3 + .../servlet24/HttpSessionTest.java | 3 + .../servlet24/ServletInputStreamTest.java | 3 + .../servlet24/ServletOutputStreamTest.java | 3 + .../servlet24/ServletRequestTest.java | 3 + .../servlet24/ServletResponseTest.java | 3 + .../servlet24/ServletTest.java | 68 ++++++++++++ .../servlet24/WebServletTest.java | 3 + .../servlet30/ApiEndpointTest.java | 8 +- .../servlet30/HttpServletServer.java | 12 +- .../ServletContainerInitializerTest.java | 8 +- .../instrumentation/servlet5/ServletTest.java | 67 ++++++++++- .../ServletContainerInitializerTest.java | 8 +- .../instrumentation/servlet6/ServletTest.java | 65 ++++++++++- .../httpServer/test/HttpServerTest.java | 104 ++++++++++++------ .../xalan/xpath/XPathTest.java | 3 + .../intcodeagent/utils/EncryptorUtils.java | 54 +++++++++ .../newrelic/api/agent/security/Agent.java | 12 +- 50 files changed, 848 insertions(+), 147 deletions(-) create mode 100644 newrelic-security-api-test-impl/src/main/java/com/newrelic/agent/security/intcodeagent/utils/EncryptorUtils.java diff --git a/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala b/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala index 05aaa5904..be3b24a32 100644 --- a/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala +++ b/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala @@ -15,12 +15,13 @@ import akka.util.ByteString import com.newrelic.agent.security.introspec.{InstrumentationTestConfig, SecurityInstrumentationTestRunner, SecurityIntrospector} import com.newrelic.api.agent.Trace import com.newrelic.api.agent.security.instrumentation.helpers.{GenericHelper, ServletHelper} -import com.newrelic.api.agent.security.schema.{SecurityMetaData, VulnerabilityCaseType} +import com.newrelic.api.agent.security.schema.{K2RequestIdentifier, SecurityMetaData, StringUtils, VulnerabilityCaseType} import com.newrelic.api.agent.security.schema.operation.{RXSSOperation, SSRFOperation} import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.{Assert, FixMethodOrder, Test} +import java.io.File import java.net.ServerSocket import java.util.UUID import scala.collection.JavaConversions @@ -44,12 +45,13 @@ class AkkaHttpCoreTest { val contentType: String = "text/plain" val responseBody: String = "Hoops!" val requestBody: String = "Hurray!" + val fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2" @Test def syncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -67,13 +69,14 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -91,13 +94,14 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def syncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -115,13 +119,14 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -139,6 +144,7 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Trace(dispatcher = true, nameTransaction = true) @@ -183,7 +189,20 @@ class AkkaHttpCoreTest { } port } - + private def assertIASTFuzzIdentifier(identifier: K2RequestIdentifier): Unit = { + val f = new File("./tmp123") + val data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false) + Assert.assertTrue(data.length > 4) + Assert.assertNotNull(identifier) + Assert.assertEquals(fuzzHeader, identifier.getRaw) + Assert.assertEquals(data(0), identifier.getApiRecordId) + Assert.assertEquals(data(1), identifier.getRefId) + Assert.assertEquals(data(2), identifier.getRefValue) + Assert.assertEquals(data(3), identifier.getNextStage.getStatus) + Assert.assertEquals(1, identifier.getTempFiles.size) + Assert.assertEquals(f.getPath, identifier.getTempFiles.get(0)) + f.deleteOnExit() + } private def assertSSRFOperation(operation: SSRFOperation, url: String): Unit = { Assert.assertFalse("operation should not be empty", operation.isEmpty) Assert.assertFalse("JNDILookup should be false", operation.isJNDILookup) diff --git a/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala b/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala index 727220cd9..4e81c7835 100644 --- a/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala +++ b/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala @@ -15,12 +15,13 @@ import akka.util.ByteString import com.newrelic.agent.security.introspec.{InstrumentationTestConfig, SecurityInstrumentationTestRunner, SecurityIntrospector} import com.newrelic.api.agent.Trace import com.newrelic.api.agent.security.instrumentation.helpers.{GenericHelper, ServletHelper} -import com.newrelic.api.agent.security.schema.{SecurityMetaData, VulnerabilityCaseType} +import com.newrelic.api.agent.security.schema.{K2RequestIdentifier, SecurityMetaData, StringUtils, VulnerabilityCaseType} import com.newrelic.api.agent.security.schema.operation.{RXSSOperation, SSRFOperation} import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.{Assert, FixMethodOrder, Test} +import java.io.File import java.net.ServerSocket import java.util.UUID import scala.collection.JavaConversions @@ -44,12 +45,13 @@ class AkkaHttpCoreTest { val contentType: String = "text/plain" val responseBody: String = "Hoops!" val requestBody: String = "Hurray!" + val fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2" @Test def syncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -67,13 +69,14 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -91,13 +94,14 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def syncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -115,13 +119,14 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -139,6 +144,7 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Trace(dispatcher = true, nameTransaction = true) @@ -199,7 +205,7 @@ class AkkaHttpCoreTest { ) Assert.assertTrue( String.format("Invalid CSEC header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headers.exists(header => header.value().contains(headerVal)) + headers.exists(header => header.value().contains(fuzzHeader)) ) Assert.assertTrue( @@ -220,6 +226,20 @@ class AkkaHttpCoreTest { headers.exists(header => header.value().contains(headerVal)) ) } + private def assertIASTFuzzIdentifier(identifier: K2RequestIdentifier): Unit = { + val f = new File("./tmp123") + val data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false) + Assert.assertTrue(data.length > 4) + Assert.assertNotNull(identifier) + Assert.assertEquals(fuzzHeader, identifier.getRaw) + Assert.assertEquals(data(0), identifier.getApiRecordId) + Assert.assertEquals(data(1), identifier.getRefId) + Assert.assertEquals(data(2), identifier.getRefValue) + Assert.assertEquals(data(3), identifier.getNextStage.getStatus) + Assert.assertEquals(1, identifier.getTempFiles.size) + Assert.assertEquals(f.getPath, identifier.getTempFiles.get(0)) + f.deleteOnExit() + } private def assertRXSSOperation(operation: RXSSOperation): Unit = { Assert.assertFalse("operation should not be empty", operation.isEmpty) Assert.assertFalse("LowSeverityHook should be disabled", operation.isLowSeverityHook) diff --git a/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala b/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala index dd1337dd3..a92ef0aa8 100644 --- a/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala +++ b/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala @@ -14,12 +14,13 @@ import akka.util.ByteString import com.newrelic.agent.security.introspec.{InstrumentationTestConfig, SecurityInstrumentationTestRunner, SecurityIntrospector} import com.newrelic.api.agent.Trace import com.newrelic.api.agent.security.instrumentation.helpers.{GenericHelper, ServletHelper} -import com.newrelic.api.agent.security.schema.{SecurityMetaData, VulnerabilityCaseType} +import com.newrelic.api.agent.security.schema.{K2RequestIdentifier, SecurityMetaData, StringUtils, VulnerabilityCaseType} import com.newrelic.api.agent.security.schema.operation.{RXSSOperation, SSRFOperation} import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.{Assert, FixMethodOrder, Test} +import java.io.File import java.net.ServerSocket import java.util.UUID import scala.concurrent.duration.DurationInt @@ -42,12 +43,13 @@ class AkkaHttpCoreTest { val contentType: String = "text/plain" val responseBody: String = "Hoops!" val requestBody: String = "Hurray!" + val fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2" @Test def syncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -65,13 +67,14 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -89,13 +92,14 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def syncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -113,13 +117,14 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(headerValue) + introspector.setK2FuzzRequestId(fuzzHeader) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -137,6 +142,7 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) + assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Trace(dispatcher = true, nameTransaction = true) @@ -181,7 +187,20 @@ class AkkaHttpCoreTest { } port } - + private def assertIASTFuzzIdentifier(identifier: K2RequestIdentifier): Unit = { + val f = new File("./tmp123") + val data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false) + Assert.assertTrue(data.length > 4) + Assert.assertNotNull(identifier) + Assert.assertEquals(fuzzHeader, identifier.getRaw) + Assert.assertEquals(data(0), identifier.getApiRecordId) + Assert.assertEquals(data(1), identifier.getRefId) + Assert.assertEquals(data(2), identifier.getRefValue) + Assert.assertEquals(data(3), identifier.getNextStage.getStatus) + Assert.assertEquals(1, identifier.getTempFiles.size) + Assert.assertEquals(f.getPath, identifier.getTempFiles.get(0)) + f.deleteOnExit() + } private def assertSSRFOperation(operation: SSRFOperation, url: String): Unit = { Assert.assertFalse("operation should not be empty", operation.isEmpty) Assert.assertFalse("JNDILookup should be false", operation.isJNDILookup) diff --git a/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java index 73c5b14d6..e27acd60a 100644 --- a/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java +++ b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java @@ -32,9 +32,6 @@ public class APIEndpointTest { public void setupEndpoints() { expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); expectedMappings.put("/index.jsp", null); - expectedMappings.put("/*.jsp", "org.apache.jasper.servlet.JspServlet"); - expectedMappings.put("/", DefaultServlet.class.getName()); - expectedMappings.put("/*.jspx", "org.apache.jasper.servlet.JspServlet"); } @Test @@ -43,7 +40,7 @@ public void testAPIEndpoint() throws Exception { Set mappings = URLMappingsHelper.getApplicationURLMappings(); Assert.assertNotNull(mappings); - Assert.assertEquals(5, mappings.size()); + Assert.assertEquals(2, mappings.size()); for (ApplicationURLMapping mapping : mappings) { assertMappings(mapping); } diff --git a/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java index e382baadf..338994b59 100644 --- a/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java +++ b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java @@ -32,9 +32,6 @@ public class APIEndpointTest { public void setupEndpoints() { expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); expectedMappings.put("/index.jsp", null); - expectedMappings.put("/*.jsp", "org.apache.jasper.servlet.JspServlet"); - expectedMappings.put("/", DefaultServlet.class.getName()); - expectedMappings.put("/*.jspx", "org.apache.jasper.servlet.JspServlet"); } @Test @@ -43,7 +40,7 @@ public void testAPIEndpoint() throws Exception { Set mappings = URLMappingsHelper.getApplicationURLMappings(); Assert.assertNotNull(mappings); - Assert.assertEquals(5, mappings.size()); + Assert.assertEquals(2, mappings.size()); for (ApplicationURLMapping mapping : mappings) { assertMappings(mapping); } diff --git a/instrumentation-security/grpc-1.22.0/src/test/java/com/nr/agent/security/instrumentation/grpc1220/GrpcTest.java b/instrumentation-security/grpc-1.22.0/src/test/java/com/nr/agent/security/instrumentation/grpc1220/GrpcTest.java index 98b4cf6a3..346d85c11 100644 --- a/instrumentation-security/grpc-1.22.0/src/test/java/com/nr/agent/security/instrumentation/grpc1220/GrpcTest.java +++ b/instrumentation-security/grpc-1.22.0/src/test/java/com/nr/agent/security/instrumentation/grpc1220/GrpcTest.java @@ -11,8 +11,11 @@ import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.K2RequestIdentifier; +import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; @@ -24,6 +27,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import java.io.File; import java.util.List; import java.util.UUID; @@ -35,6 +39,7 @@ public class GrpcTest { private static TestServer server; private static TestClient client; + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @BeforeClass public static void before() throws Exception { @@ -58,8 +63,9 @@ public void testBlockingRequest() throws JsonProcessingException { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); introspector.setK2TracingData(headerValue); + introspector.setK2ParentId(headerValue); client.helloBlocking("Blocking"); @@ -90,14 +96,18 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Blocking\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Blocking\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -105,8 +115,9 @@ public void testFutureRequest() throws Exception { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); introspector.setK2TracingData(headerValue); + introspector.setK2ParentId(headerValue); client.helloFuture("Future"); @@ -137,14 +148,18 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Future\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Future\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -152,8 +167,9 @@ public void testAsyncRequest() throws JsonProcessingException, InterruptedExcept String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); introspector.setK2TracingData(headerValue); + introspector.setK2ParentId(headerValue); client.helloAsync("Async"); // wait for async call to finish @@ -186,14 +202,18 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Async\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Async\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -201,8 +221,9 @@ public void testStreamingRequest() throws JsonProcessingException, InterruptedEx String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); introspector.setK2TracingData(headerValue); + introspector.setK2ParentId(headerValue); client.helloStreaming("Streaming"); // wait for streaming to finish @@ -235,13 +256,31 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Streaming1\"},{\"name\":\"Streaming2\"},{\"name\":\"Streaming3\"},{\"name\":\"Streaming4\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Streaming1\"},{\"message\":\"Hello Streaming2\"},{\"message\":\"Hello Streaming3\"},{\"message\":\"Hello Streaming4\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); + } + private void assertCSECHeaders(K2RequestIdentifier identifier){ + File f = new File("./tmp123"); + String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); + Assert.assertTrue(data.length > 4); + Assert.assertNotNull(identifier); + Assert.assertEquals(fuzzHeader, identifier.getRaw()); + Assert.assertEquals(data[0], identifier.getApiRecordId()); + Assert.assertEquals(data[1], identifier.getRefId()); + Assert.assertEquals(data[2], identifier.getRefValue()); + Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); + Assert.assertEquals(1, identifier.getTempFiles().size()); + Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); + f.deleteOnExit(); } } diff --git a/instrumentation-security/grpc-1.4.0/src/test/java/com/nr/agent/security/instrumentation/grpc140/GrpcTest.java b/instrumentation-security/grpc-1.4.0/src/test/java/com/nr/agent/security/instrumentation/grpc140/GrpcTest.java index afb94e295..775e5bc1e 100644 --- a/instrumentation-security/grpc-1.4.0/src/test/java/com/nr/agent/security/instrumentation/grpc140/GrpcTest.java +++ b/instrumentation-security/grpc-1.4.0/src/test/java/com/nr/agent/security/instrumentation/grpc140/GrpcTest.java @@ -8,6 +8,9 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.K2RequestIdentifier; +import com.newrelic.api.agent.security.schema.StringUtils; import com.nr.agent.security.instrumentation.grpc140.app.TestServer; import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; @@ -24,6 +27,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import java.io.File; import java.util.List; import java.util.UUID; @@ -35,6 +39,7 @@ public class GrpcTest { private static TestServer server; private static TestClient client; + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @BeforeClass public static void before() throws Exception { @@ -58,8 +63,9 @@ public void testBlockingRequest() throws JsonProcessingException { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); introspector.setK2TracingData(headerValue); + introspector.setK2ParentId(headerValue); client.helloBlocking("Blocking"); @@ -90,14 +96,18 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Blocking\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Blocking\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -105,8 +115,9 @@ public void testFutureRequest() throws Exception { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); introspector.setK2TracingData(headerValue); + introspector.setK2ParentId(headerValue); client.helloFuture("Future"); @@ -137,14 +148,18 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Future\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Future\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -152,7 +167,8 @@ public void testAsyncRequest() throws JsonProcessingException, InterruptedExcept String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2ParentId(headerValue); introspector.setK2TracingData(headerValue); client.helloAsync("Async"); @@ -186,14 +202,18 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Async\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Async\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -201,7 +221,8 @@ public void testStreamingRequest() throws JsonProcessingException, InterruptedEx String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2ParentId(headerValue); introspector.setK2TracingData(headerValue); client.helloStreaming("Streaming"); @@ -235,13 +256,31 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Streaming1\"},{\"name\":\"Streaming2\"},{\"name\":\"Streaming3\"},{\"name\":\"Streaming4\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Streaming1\"},{\"message\":\"Hello Streaming2\"},{\"message\":\"Hello Streaming3\"},{\"message\":\"Hello Streaming4\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); + } + private void assertCSECHeaders(K2RequestIdentifier identifier){ + File f = new File("./tmp123"); + String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); + Assert.assertTrue(data.length > 4); + Assert.assertNotNull(identifier); + Assert.assertEquals(fuzzHeader, identifier.getRaw()); + Assert.assertEquals(data[0], identifier.getApiRecordId()); + Assert.assertEquals(data[1], identifier.getRefId()); + Assert.assertEquals(data[2], identifier.getRefValue()); + Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); + Assert.assertEquals(1, identifier.getTempFiles().size()); + Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); + f.deleteOnExit(); } } diff --git a/instrumentation-security/grpc-1.40.0/src/test/java/com/nr/agent/security/instrumentation/grpc1400/GrpcTest.java b/instrumentation-security/grpc-1.40.0/src/test/java/com/nr/agent/security/instrumentation/grpc1400/GrpcTest.java index bfe97effa..5b1d57174 100644 --- a/instrumentation-security/grpc-1.40.0/src/test/java/com/nr/agent/security/instrumentation/grpc1400/GrpcTest.java +++ b/instrumentation-security/grpc-1.40.0/src/test/java/com/nr/agent/security/instrumentation/grpc1400/GrpcTest.java @@ -11,8 +11,11 @@ import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.K2RequestIdentifier; +import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; @@ -24,6 +27,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import java.io.File; import java.util.List; import java.util.UUID; @@ -35,6 +39,7 @@ public class GrpcTest { private static TestServer server; private static TestClient client; + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @BeforeClass public static void before() throws Exception { @@ -58,8 +63,9 @@ public void testBlockingRequest() throws JsonProcessingException { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); introspector.setK2TracingData(headerValue); + introspector.setK2ParentId(headerValue); client.helloBlocking("Blocking"); @@ -89,15 +95,18 @@ else if (op instanceof RXSSOperation) { Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Blocking\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Blocking\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -105,8 +114,9 @@ public void testFutureRequest() throws Exception { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); introspector.setK2TracingData(headerValue); + introspector.setK2ParentId(headerValue); client.helloFuture("Future"); @@ -137,14 +147,18 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Future\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Future\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -152,8 +166,9 @@ public void testAsyncRequest() throws JsonProcessingException, InterruptedExcept String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); introspector.setK2TracingData(headerValue); + introspector.setK2ParentId(headerValue); client.helloAsync("Async"); // wait for async call to finish @@ -186,14 +201,18 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Async\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Async\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -201,8 +220,9 @@ public void testStreamingRequest() throws JsonProcessingException, InterruptedEx String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(headerValue); + introspector.setK2FuzzRequestId(fuzzHeader); introspector.setK2TracingData(headerValue); + introspector.setK2ParentId(headerValue); client.helloStreaming("Streaming"); // wait for streaming to finish @@ -235,13 +255,31 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Streaming1\"},{\"name\":\"Streaming2\"},{\"name\":\"Streaming3\"},{\"name\":\"Streaming4\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Streaming1\"},{\"message\":\"Hello Streaming2\"},{\"message\":\"Hello Streaming3\"},{\"message\":\"Hello Streaming4\"}]", response); + assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); + } + private void assertCSECHeaders(K2RequestIdentifier identifier){ + File f = new File("./tmp123"); + String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); + Assert.assertTrue(data.length > 4); + Assert.assertNotNull(identifier); + Assert.assertEquals(fuzzHeader, identifier.getRaw()); + Assert.assertEquals(data[0], identifier.getApiRecordId()); + Assert.assertEquals(data[1], identifier.getRefId()); + Assert.assertEquals(data[2], identifier.getRefValue()); + Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); + Assert.assertEquals(1, identifier.getTempFiles().size()); + Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); + f.deleteOnExit(); } } diff --git a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java index 6f0e71eae..ae2c1e942 100644 --- a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java +++ b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java @@ -7,9 +7,11 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; import com.newrelic.agent.security.instrumentation.javax.jndi.JNDIUtils; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -30,6 +32,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.naming", "com.newrelic.agent.security.instrumentation.javax.jndi" } ) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Category({ Java17IncompatibleTest.class}) public class ContextRmiTest { private final int PORT = getRandomPort(); diff --git a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java index b4295dc77..fd5118c93 100644 --- a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java +++ b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java @@ -7,12 +7,14 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; import com.newrelic.agent.security.instrumentation.javax.jndi.JNDIUtils; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import com.unboundid.ldap.sdk.LDAPException; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.zapodot.junit.ldap.EmbeddedLdapRule; @@ -30,6 +32,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.naming", "com.newrelic.agent.security.instrumentation.javax.jndi" } ) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Category({ Java17IncompatibleTest.class}) public class ContextTest { public static final String DOMAIN_DSN = "dc=example,dc=com"; @ClassRule diff --git a/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java b/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java index 4d50e493c..aa134a824 100644 --- a/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java +++ b/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.LDAPOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.LDAPInterface; import org.junit.Assert; @@ -14,6 +15,7 @@ import org.junit.FixMethodOrder; import org.junit.Ignore; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.zapodot.junit.ldap.EmbeddedLdapRule; @@ -35,6 +37,7 @@ @FixMethodOrder(MethodSorters.NAME_ASCENDING) //FIXME: after instrumentation works @Ignore +@Category({ Java17IncompatibleTest.class}) public class DirContextTest { public static final String DOMAIN_DSN = "dc=example,dc=com"; @ClassRule diff --git a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java index 4146f3dff..ad54598aa 100644 --- a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java +++ b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java @@ -4,13 +4,16 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.App; import org.junit.Assert; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "com.newrelic.agent.security.instrumentation.javax.ws.rs.api") +@Category({ Java17IncompatibleTest.class}) public class JavaxWsRsApiTest { @Test public void testPut() { diff --git a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java index 61befaaf5..bad3be5a9 100644 --- a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java +++ b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java @@ -1,5 +1,6 @@ package com.nr.agent.security.instrumentation.javax.ws.rs.api.test; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.CustomerLocatorResource; import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.IdSubResource; import com.newrelic.agent.security.introspec.InstrumentationTestConfig; @@ -13,6 +14,7 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import javax.ws.rs.client.Entity; @@ -21,6 +23,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "com.newrelic.agent.security.instrumentation.javax.ws.rs.api") +@Category({ Java17IncompatibleTest.class}) public class SubresourceTest extends JerseyTest { @BeforeClass public static void bringUp() { diff --git a/instrumentation-security/jaxen-xpath-1.1/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java b/instrumentation-security/jaxen-xpath-1.1/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java index 9e3579340..21e3a1a5b 100644 --- a/instrumentation-security/jaxen-xpath-1.1/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java +++ b/instrumentation-security/jaxen-xpath-1.1/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.XPathOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.jaxen.BaseXPath; import org.jaxen.Context; import org.jaxen.ContextSupport; @@ -18,6 +19,7 @@ import org.jaxen.xom.XOMXPath; import org.junit.Assert; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.w3c.dom.Document; @@ -26,6 +28,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "com.newrelic.agent.security.instrumentation.xpath.jaxen", "org.jaxen" }) +@Category({ Java17IncompatibleTest.class}) public class BaseXPathTest { private final String EXPRESSION = "/Customers/Customer"; private final String XML_DOC = "src/test/resources/Customer.xml"; diff --git a/instrumentation-security/jaxen-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java b/instrumentation-security/jaxen-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java index a370cb9d2..01a62ce9e 100644 --- a/instrumentation-security/jaxen-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java +++ b/instrumentation-security/jaxen-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.XPathOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.jaxen.BaseXPath; import org.jaxen.Context; import org.jaxen.ContextSupport; @@ -18,6 +19,7 @@ import org.jaxen.xom.XOMXPath; import org.junit.Assert; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.w3c.dom.Document; @@ -27,6 +29,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "com.newrelic.instrumentation.security.xpath.jaxen", "org.jaxen" }) +@Category({ Java17IncompatibleTest.class}) public class BaseXPathTest { private final String EXPRESSION = "/Customers/Customer"; private final String XML_DOC = "src/test/resources/Customer.xml"; diff --git a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DataStoreTest.java b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DataStoreTest.java index 413309216..53d4c81df 100644 --- a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DataStoreTest.java +++ b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DataStoreTest.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -37,7 +38,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DriverTest.java b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DriverTest.java index 52a165ea4..51158d48c 100644 --- a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DriverTest.java +++ b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DriverTest.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -29,7 +30,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/PgStatementTest.java b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/PgStatementTest.java index 63c84079e..44e39e502 100644 --- a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/PgStatementTest.java +++ b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/PgStatementTest.java @@ -8,6 +8,7 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SQLOperation; import com.newrelic.security.test.marker.Java12IncompatibleTest; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -37,7 +38,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DataStoreTest.java b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DataStoreTest.java index f99de0c46..f597ecb4d 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DataStoreTest.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DataStoreTest.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -38,7 +39,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DriverTest.java b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DriverTest.java index 92a741464..9c6e675d7 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DriverTest.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DriverTest.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -29,7 +30,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/PgStatementTest.java b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/PgStatementTest.java index 48b935998..52865421c 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/PgStatementTest.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/PgStatementTest.java @@ -8,6 +8,7 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SQLOperation; import com.newrelic.security.test.marker.Java12IncompatibleTest; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -37,7 +38,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DataStoreTest.java b/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DataStoreTest.java index 336e52ad7..89ac790ed 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DataStoreTest.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DataStoreTest.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -38,7 +39,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DriverTest.java b/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DriverTest.java index 1dc172a07..bb8bfe5ac 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DriverTest.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DriverTest.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -30,7 +31,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; import static ru.yandex.qatools.embed.postgresql.distribution.Version.V11_1; -@Category({ Java12IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java b/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java index d3ccc680e..472b63421 100644 --- a/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java +++ b/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java @@ -59,7 +59,7 @@ @InstrumentationTestConfig(includePrefixes = {"com.newrelic.agent.security.instrumentation.jersey2", "org.glassfish.jersey"}) @Category({ Java9IncompatibleTest.class, Java11IncompatibleTest.class, Java17IncompatibleTest.class }) public class JerseyTests { - + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; private static HttpServer server; private static int port; private static final String PACKAGE = "com.nr.agent.security.instrumentation.jersey2.resources"; @@ -136,7 +136,7 @@ private String[] fireRequest1(final String path) { Client client = ClientBuilder.newClient(); WebTarget target = client.target(url.toString()).path(path); try ( Response response = target.request().header(Header.ContentType.toString(), MediaType.APPLICATION_JSON) - .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue) + .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader) .header(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue) .header(GenericHelper.CSEC_PARENT_ID, headerValue) .get(); @@ -177,7 +177,7 @@ private void assertOperation(List operations, boolean hasHead ); assertEquals( String.format("Invalid CSEC header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headerValue, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + fuzzHeader, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); assertTrue( String.format("Missing CSEC header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), diff --git a/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java b/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java index f418c45e8..506842f14 100644 --- a/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java +++ b/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java @@ -65,6 +65,7 @@ public class JerseyTests { private static final String PACKAGE = "com.nr.agent.security.instrumentation.jersey2.resources"; private static URL url; private final String headerValue = String.valueOf(UUID.randomUUID()); + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @BeforeClass public static void setUp() throws MalformedURLException, URISyntaxException { @@ -138,7 +139,7 @@ private String[] fireRequest1(final String path) { Client client = ClientBuilder.newClient(); WebTarget target = client.target(url.toString()).path(path); Response response = target.request().header(Header.ContentType.toString(), MediaType.APPLICATION_JSON) - .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue) + .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader) .header(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue) .header(GenericHelper.CSEC_PARENT_ID, headerValue) .get(); @@ -180,7 +181,7 @@ private void assertOperation(List operations, boolean hasHead ); assertEquals( String.format("Invalid CSEC header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headerValue, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + fuzzHeader, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); assertTrue( String.format("Missing CSEC header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), diff --git a/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java b/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java index 85ec2d538..4b67f8644 100644 --- a/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java +++ b/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java @@ -58,7 +58,7 @@ @InstrumentationTestConfig(includePrefixes = {"com.newrelic.agent.security.instrumentation.jersey2", "org.glassfish.jersey"}) @Category({Java8IncompatibleTest.class, Java11IncompatibleTest.class}) public class JerseyTests { - + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; private static HttpServer server; private static int port; private static final String PACKAGE = "com.nr.agent.security.instrumentation.jersey2.resources"; @@ -135,7 +135,7 @@ private String[] fireRequest1(final String path) { Client client = ClientBuilder.newClient(); WebTarget target = client.target(url.toString()).path(path); try ( Response response = target.request().header(Header.ContentType.toString(), MediaType.APPLICATION_JSON) - .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue) + .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader) .header(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue) .header(GenericHelper.CSEC_PARENT_ID, headerValue) .get(); @@ -177,7 +177,7 @@ private void assertOperation(List operations, boolean hasHead ); assertEquals( String.format("Invalid CSEC header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headerValue, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + fuzzHeader, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); assertTrue( String.format("Missing CSEC header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), diff --git a/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java b/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java index 78269c9d6..09cd81957 100644 --- a/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java +++ b/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java @@ -4,11 +4,14 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.api.agent.security.schema.K2RequestIdentifier; +import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.agent.security.instrumentation.jetty11.HttpServletHelper; @@ -16,11 +19,9 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.junit.After; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; @@ -29,11 +30,12 @@ import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + +import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.ServerSocket; import java.net.URL; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -47,13 +49,6 @@ public class ServerTest { public final static String ENDPOINT = String.format("http://localhost:%d/", PORT); private Server server; - - private static final Map actualMappings = new HashMap<>(); - @BeforeClass - public static void addMappings() { - actualMappings.put("/servlet/*", MyServlet.class.getName()); - actualMappings.put("/", ServletHandler.Default404Servlet.class.getName()); - } @After public void teardown() throws Exception { if (server.isRunning()) { @@ -201,18 +196,96 @@ public void testAPIEndpoint () throws Exception { start(); Set mappings = URLMappingsHelper.getApplicationURLMappings(); - Assert.assertEquals(2, mappings.size()); + Assert.assertEquals(1, mappings.size()); for (ApplicationURLMapping mapping : mappings) { Assert.assertNotNull(mapping); Assert.assertNotNull(mapping.getHandler()); Assert.assertNotNull(mapping.getPath()); Assert.assertNotNull(mapping.getMethod()); - - Assert.assertEquals(actualMappings.get(mapping.getPath()), mapping.getHandler()); + Assert.assertEquals("/servlet/*", mapping.getPath());; + Assert.assertEquals(MyServlet.class.getName(), mapping.getHandler()); Assert.assertEquals("*", mapping.getMethod()); } } + @Test + public void testCSECHeaders() throws Exception { + start(); + String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; + String headerValue = serviceWithHeaders(fuzzHeader); + + Thread.sleep(100); + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertFalse("No operations detected", operations.isEmpty()); + Assert.assertEquals("Extra operations detected", 1, operations.size()); + + RXSSOperation targetOperation = (RXSSOperation) operations.get(0); + Assert.assertNotNull("No target operation detected", targetOperation); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); + Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); + Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); + + Assert.assertEquals("Wrong port detected", PORT, targetOperation.getRequest().getServerPort()); + Assert.assertEquals("Wrong method name detected", "handle", targetOperation.getMethodName()); + Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); + + Map headers = targetOperation.getRequest().getHeaders(); + Assert.assertTrue( + String.format("Missing header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), + headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), + fuzzHeader, + headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + ); + Assert.assertTrue( + String.format("Missing header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), + headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), + headerValue, + headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) + ); + Assert.assertTrue( + String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), + headers.containsKey(GenericHelper.CSEC_PARENT_ID) + ); + Assert.assertEquals( + String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), + headerValue, headers.get(GenericHelper.CSEC_PARENT_ID) + ); + + File f = new File("./tmp123"); + K2RequestIdentifier identifier = introspector.getSecurityMetaData().getFuzzRequestIdentifier(); + String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); + Assert.assertTrue(data.length > 4); + Assert.assertNotNull(identifier); + Assert.assertEquals(fuzzHeader, identifier.getRaw()); + Assert.assertEquals(data[0], identifier.getApiRecordId()); + Assert.assertEquals(data[1], identifier.getRefId()); + Assert.assertEquals(data[2], identifier.getRefValue()); + Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); + Assert.assertEquals(1, identifier.getTempFiles().size()); + Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); + f.deleteOnExit(); + } + @Trace(dispatcher = true) + private String serviceWithHeaders(String fuzzHeader) throws IOException { + String headerValue = String.valueOf(UUID.randomUUID()); + URL url = new URL(ENDPOINT); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); + + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); + conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); + conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); + conn.connect(); + conn.getResponseCode(); + return headerValue; + } private void start() throws Exception { server = new Server(PORT); ServletHolder holder = new ServletHolder(new MyServlet()); diff --git a/instrumentation-security/jetty-12/src/test/java/com/nr/agent/security/instrumentation/jetty12/test/ServerTest.java b/instrumentation-security/jetty-12/src/test/java/com/nr/agent/security/instrumentation/jetty12/test/ServerTest.java index 71bcdb51c..b4cac74de 100644 --- a/instrumentation-security/jetty-12/src/test/java/com/nr/agent/security/instrumentation/jetty12/test/ServerTest.java +++ b/instrumentation-security/jetty-12/src/test/java/com/nr/agent/security/instrumentation/jetty12/test/ServerTest.java @@ -4,6 +4,7 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -41,7 +42,7 @@ public class ServerTest { public static int PORT = 0; public static String ENDPOINT = "http://localhost:%d/"; - + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; private Server server; @After @@ -83,7 +84,7 @@ public void testHandle() throws Exception { ); Assert.assertEquals( String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headerValue, + fuzzHeader, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); Assert.assertTrue( @@ -95,6 +96,15 @@ public void testHandle() throws Exception { headerValue, headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) ); + Assert.assertTrue( + String.format("Missing header: %s", GenericHelper.CSEC_PARENT_ID), + headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase()) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", GenericHelper.CSEC_PARENT_ID), + headerValue, + headers.get(GenericHelper.CSEC_PARENT_ID.toLowerCase()) + ); } @Test @@ -127,7 +137,7 @@ public void testHandle1() throws Exception { ); Assert.assertEquals( String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headerValue, + fuzzHeader, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); Assert.assertTrue( @@ -139,6 +149,15 @@ public void testHandle1() throws Exception { headerValue, headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) ); + Assert.assertTrue( + String.format("Missing header: %s", GenericHelper.CSEC_PARENT_ID), + headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase()) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", GenericHelper.CSEC_PARENT_ID), + headerValue, + headers.get(GenericHelper.CSEC_PARENT_ID.toLowerCase()) + ); } @Test @@ -247,7 +266,7 @@ public void testHandle5() throws Exception { ); Assert.assertEquals( String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headerValue, + fuzzHeader, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); Assert.assertTrue( @@ -259,6 +278,15 @@ public void testHandle5() throws Exception { headerValue, headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) ); + Assert.assertTrue( + String.format("Missing header: %s", GenericHelper.CSEC_PARENT_ID), + headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase()) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", GenericHelper.CSEC_PARENT_ID), + headerValue, + headers.get(GenericHelper.CSEC_PARENT_ID.toLowerCase()) + ); } private void startWithServlet() throws Exception { @@ -320,8 +348,9 @@ private String serviceWithHeaders() throws Exception { conn.setRequestProperty("content-type", "text/plain;charset=utf-8"); conn.setRequestMethod("GET"); - conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue); + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); + conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); conn.connect(); conn.getResponseCode(); diff --git a/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java b/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java index e7f236937..5e05a60c2 100644 --- a/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java +++ b/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java @@ -4,14 +4,18 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.api.agent.security.schema.K2RequestIdentifier; +import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.agent.security.instrumentation.jetty9.HttpServletHelper; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; @@ -21,15 +25,18 @@ import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.ServerSocket; +import java.net.URISyntaxException; import java.net.URL; import java.util.List; import java.util.Map; @@ -39,6 +46,7 @@ @FixMethodOrder(MethodSorters.NAME_ASCENDING) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = {"org.eclipse.jetty", "com.newrelic.agent.security.instrumentation.jetty9"}) +@Category({ Java17IncompatibleTest.class}) public class ServerTest { public final static int PORT = getRandomPort(); public final static String ENDPOINT = String.format("http://localhost:%d/", PORT); @@ -186,6 +194,84 @@ public void testHandle3() throws Exception { Assert.assertEquals("Wrong port detected", PORT, operation.getRequest().getServerPort()); Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getRequest().getContentType()); } + @Test + public void testCSECHeaders() throws Exception { + start1(); + String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; + String headerValue = serviceWithHeaders(fuzzHeader); + + Thread.sleep(100); + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertFalse("No operations detected", operations.isEmpty()); + Assert.assertEquals("Extra operations detected", 1, operations.size()); + + RXSSOperation targetOperation = (RXSSOperation) operations.get(0); + Assert.assertNotNull("No target operation detected", targetOperation); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); + Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); + Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); + + Assert.assertEquals("Wrong port detected", PORT, targetOperation.getRequest().getServerPort()); + Assert.assertEquals("Wrong method name detected", "handle", targetOperation.getMethodName()); + Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); + + Map headers = targetOperation.getRequest().getHeaders(); + Assert.assertTrue( + String.format("Missing header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), + headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), + fuzzHeader, + headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + ); + Assert.assertTrue( + String.format("Missing header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), + headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), + headerValue, + headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) + ); + Assert.assertTrue( + String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), + headers.containsKey(GenericHelper.CSEC_PARENT_ID) + ); + Assert.assertEquals( + String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), + headerValue, headers.get(GenericHelper.CSEC_PARENT_ID) + ); + + File f = new File("./tmp123"); + K2RequestIdentifier identifier = introspector.getSecurityMetaData().getFuzzRequestIdentifier(); + String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); + Assert.assertTrue(data.length > 4); + Assert.assertNotNull(identifier); + Assert.assertEquals(fuzzHeader, identifier.getRaw()); + Assert.assertEquals(data[0], identifier.getApiRecordId()); + Assert.assertEquals(data[1], identifier.getRefId()); + Assert.assertEquals(data[2], identifier.getRefValue()); + Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); + Assert.assertEquals(1, identifier.getTempFiles().size()); + Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); + f.deleteOnExit(); + } + @Trace(dispatcher = true) + private String serviceWithHeaders(String fuzzHeader) throws IOException, URISyntaxException { + String headerValue = String.valueOf(UUID.randomUUID()); + URL url = new URL(ENDPOINT); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); + + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); + conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); + conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); + conn.connect(); + conn.getResponseCode(); + return headerValue; + } @Test public void testAPIEndpoint () throws Exception { diff --git a/instrumentation-security/jsp-2.4/src/test/java/com/nr/agent/security/instrumentation/jsp24/HttpJspPageTest.java b/instrumentation-security/jsp-2.4/src/test/java/com/nr/agent/security/instrumentation/jsp24/HttpJspPageTest.java index d79bce835..403c7f0b6 100644 --- a/instrumentation-security/jsp-2.4/src/test/java/com/nr/agent/security/instrumentation/jsp24/HttpJspPageTest.java +++ b/instrumentation-security/jsp-2.4/src/test/java/com/nr/agent/security/instrumentation/jsp24/HttpJspPageTest.java @@ -5,6 +5,7 @@ import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleState; @@ -15,6 +16,7 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import javax.servlet.ServletException; @@ -32,6 +34,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "javax.servlet.jsp") +@Category({ Java17IncompatibleTest.class}) public class HttpJspPageTest { private static final int port = getRandomPort(); private static Tomcat server; diff --git a/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresStatementTest.java b/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresStatementTest.java index 7ad8a7f9a..2b5168296 100644 --- a/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresStatementTest.java +++ b/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresStatementTest.java @@ -8,6 +8,7 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SQLOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import io.r2dbc.spi.Connection; import io.r2dbc.spi.ConnectionFactories; import io.r2dbc.spi.ConnectionFactory; @@ -16,6 +17,7 @@ import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import reactor.core.publisher.Mono; @@ -33,6 +35,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @InstrumentationTestConfig(includePrefixes = "io.r2dbc.spi") +@Category({ Java17IncompatibleTest.class }) public class PostgresStatementTest { public static final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6); diff --git a/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresTest.java b/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresTest.java index e54d93ba6..dfc23de6f 100644 --- a/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresTest.java +++ b/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresTest.java @@ -8,6 +8,7 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SQLOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import io.r2dbc.spi.Connection; import io.r2dbc.spi.ConnectionFactories; import io.r2dbc.spi.ConnectionFactory; @@ -17,6 +18,7 @@ import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import reactor.core.publisher.Flux; @@ -33,6 +35,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @InstrumentationTestConfig(includePrefixes = "io.r2dbc.spi") +@Category({ Java17IncompatibleTest.class }) public class PostgresTest { public static final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6); public static Connection connection; diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletTest.java index 36af9c86d..2657f0727 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletTest.java @@ -5,10 +5,12 @@ import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -21,6 +23,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Category({ Java17IncompatibleTest.class}) public class HttpServletTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java index 663714725..c14c32273 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java @@ -7,10 +7,12 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SecureCookieOperation; import com.newrelic.api.agent.security.schema.operation.TrustBoundaryOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -23,6 +25,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Category({ Java17IncompatibleTest.class}) public class HttpSessionTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletInputStreamTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletInputStreamTest.java index e694252ef..65557fa60 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletInputStreamTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletInputStreamTest.java @@ -8,10 +8,12 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -25,6 +27,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Category({ Java17IncompatibleTest.class}) public class ServletInputStreamTest { @ClassRule diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java index ec8969eb0..5ce24e91d 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java @@ -9,10 +9,12 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -28,6 +30,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Category({ Java17IncompatibleTest.class}) public class ServletOutputStreamTest { @ClassRule diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletRequestTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletRequestTest.java index 040018fae..b7d00f757 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletRequestTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletRequestTest.java @@ -11,10 +11,12 @@ import com.newrelic.api.agent.Trace; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -34,6 +36,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24"}) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Category({ Java17IncompatibleTest.class}) public class ServletRequestTest { @ClassRule diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletResponseTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletResponseTest.java index 98cdd0719..eca5d940c 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletResponseTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletResponseTest.java @@ -8,10 +8,12 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -28,6 +30,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24"}) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Category({ Java17IncompatibleTest.class}) public class ServletResponseTest { @ClassRule public static HttpServletServer servlet = new HttpServletServer(); diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletTest.java index eaaf384de..58bc8bc56 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletTest.java @@ -4,30 +4,42 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.K2RequestIdentifier; +import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.util.List; +import java.util.Map; +import java.util.UUID; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = {"javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24"}) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Category({ Java17IncompatibleTest.class}) public class ServletTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); + private final String headerValue = String.valueOf(UUID.randomUUID()); + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @Test public void testService() throws Exception { @@ -37,6 +49,24 @@ public void testService() throws Exception { List operations = introspector.getOperations(); Assert.assertTrue("No operations detected", operations.size() > 0); + RXSSOperation targetOperation = (RXSSOperation) operations.get(0); + Assert.assertNotNull("No target operation detected", targetOperation); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); + Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); + Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); + + Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); + Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); + Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); + } + @Test + public void testServiceWithHeaders() throws Exception { + serviceWithHeaders(); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertTrue("No operations detected", operations.size() > 0); + RXSSOperation targetOperation = (RXSSOperation) operations.get(0); Assert.assertNotNull("No target operation detected", targetOperation); Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); @@ -46,8 +76,21 @@ public void testService() throws Exception { Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); + assertCSECHeaders(targetOperation.getRequest().getHeaders()); + assertIASTIdentifier(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } + private void assertCSECHeaders(Map headers){ + Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue, headers.get( + ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, headers.get( + ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, headers.get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); + } @Trace(dispatcher = true) private void service() throws IOException, URISyntaxException { URL u = server.getEndPoint("test").toURL(); @@ -56,4 +99,29 @@ private void service() throws IOException, URISyntaxException { conn.connect(); conn.getResponseCode(); } + @Trace(dispatcher = true) + private void serviceWithHeaders() throws IOException, URISyntaxException { + URL u = server.getEndPoint("test").toURL(); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); + conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); + conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); + conn.connect(); + conn.getResponseCode(); + } + private void assertIASTIdentifier(K2RequestIdentifier identifier){ + File f = new File("./tmp123"); + String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); + Assert.assertTrue(data.length > 4); + Assert.assertNotNull(identifier); + Assert.assertEquals(fuzzHeader, identifier.getRaw()); + Assert.assertEquals(data[0], identifier.getApiRecordId()); + Assert.assertEquals(data[1], identifier.getRefId()); + Assert.assertEquals(data[2], identifier.getRefValue()); + Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); + Assert.assertEquals(1, identifier.getTempFiles().size()); + Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); + f.deleteOnExit(); + } } diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/WebServletTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/WebServletTest.java index 9606ee042..c297e5630 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/WebServletTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/WebServletTest.java @@ -6,9 +6,11 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.AgentMetaData; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import java.io.IOException; @@ -18,6 +20,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) +@Category({ Java17IncompatibleTest.class}) public class WebServletTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); diff --git a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java index 9da366969..d137e9e49 100644 --- a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java +++ b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java @@ -20,16 +20,10 @@ public class ApiEndpointTest { @Test public void testURLMappings() { - String handler = DefaultServlet.class.getName(); - String method = "*"; Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); Assert.assertTrue("URL Mappings", mappings.hasNext()); ApplicationURLMapping mapping1 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); - - Assert.assertTrue("URL Mappings", mappings.hasNext()); - ApplicationURLMapping mapping2 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping("*", "/*", MyServlet.class.getName()), mapping1); } } diff --git a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java index de666f5f6..171520001 100644 --- a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java +++ b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java @@ -13,6 +13,9 @@ import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.net.ServerSocket; @@ -64,7 +67,7 @@ public void onStartup(Set> c, ServletContext ctx){ } }, Collections.emptySet()); - Tomcat.addServlet(context, "servlet", new DefaultServlet()); + Tomcat.addServlet(context, "servlet", new MyServlet()); context.addServletMappingDecoded("/*","servlet"); context.addServletMappingDecoded("/test","servlet"); @@ -88,4 +91,11 @@ private void stop() { } } } +} + +class MyServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + super.doGet(req, resp); + } } \ No newline at end of file diff --git a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java index 125c81fba..32b4263bb 100644 --- a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java +++ b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java @@ -19,16 +19,10 @@ public class ServletContainerInitializerTest { @Test public void testURLMappings() { - String handler = "com.nr.agent.security.instrumentation.servlet5.HttpTestServlet"; - String method = "*"; Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); Assert.assertTrue("URL Mappings", mappings.hasNext()); ApplicationURLMapping mapping1 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); - - Assert.assertTrue("URL Mappings", mappings.hasNext()); - ApplicationURLMapping mapping2 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping("*", "/*", HttpTestServlet.class.getName()), mapping1); } } diff --git a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletTest.java b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletTest.java index bd9ed014b..53c305939 100644 --- a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletTest.java +++ b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletTest.java @@ -4,7 +4,11 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.K2RequestIdentifier; +import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; @@ -15,11 +19,14 @@ import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.util.List; +import java.util.Map; +import java.util.UUID; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = {"jakarta.servlet", "com.newrelic.agent.security.instrumentation.servlet5"}) @@ -28,6 +35,8 @@ public class ServletTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); + private final String headerValue = String.valueOf(UUID.randomUUID()); + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @Test public void testService() throws Exception { @@ -42,12 +51,43 @@ public void testService() throws Exception { Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); - + + Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); + Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); + Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); + } + @Test + public void testServiceWithHeaders() throws Exception { + serviceWithHeaders(); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertTrue("No operations detected", operations.size() > 0); + + RXSSOperation targetOperation = (RXSSOperation) operations.get(0); + Assert.assertNotNull("No target operation detected", targetOperation); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); + Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); + Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); + Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); + assertCSECHeaders(targetOperation.getRequest().getHeaders()); + assertIASTIdentifier(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } + private void assertCSECHeaders(Map headers){ + Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue, headers.get( + ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, headers.get( + ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, headers.get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); + } @Trace(dispatcher = true) private void service() throws IOException, URISyntaxException { URL u = server.getEndPoint("test").toURL(); @@ -56,4 +96,29 @@ private void service() throws IOException, URISyntaxException { conn.connect(); conn.getResponseCode(); } + @Trace(dispatcher = true) + private void serviceWithHeaders() throws IOException, URISyntaxException { + URL u = server.getEndPoint("test").toURL(); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); + conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); + conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); + conn.connect(); + conn.getResponseCode(); + } + private void assertIASTIdentifier(K2RequestIdentifier identifier){ + File f = new File("./tmp123"); + String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); + Assert.assertTrue(data.length > 4); + Assert.assertNotNull(identifier); + Assert.assertEquals(fuzzHeader, identifier.getRaw()); + Assert.assertEquals(data[0], identifier.getApiRecordId()); + Assert.assertEquals(data[1], identifier.getRefId()); + Assert.assertEquals(data[2], identifier.getRefValue()); + Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); + Assert.assertEquals(1, identifier.getTempFiles().size()); + Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); + f.deleteOnExit(); + } } diff --git a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java index 04c224897..83a4c1bb1 100644 --- a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java +++ b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java @@ -19,16 +19,10 @@ public class ServletContainerInitializerTest { @Test public void testURLMappings() { - String handler = "com.nr.agent.security.instrumentation.servlet6.HttpTestServlet"; - String method = "*"; Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); Assert.assertTrue("URL Mappings", mappings.hasNext()); ApplicationURLMapping mapping1 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); - - Assert.assertTrue("URL Mappings", mappings.hasNext()); - ApplicationURLMapping mapping2 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping("*", "/*", HttpTestServlet.class.getName()), mapping1); } } diff --git a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletTest.java b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletTest.java index 8e0124b82..314109280 100644 --- a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletTest.java +++ b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletTest.java @@ -4,7 +4,11 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.K2RequestIdentifier; +import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; @@ -15,11 +19,14 @@ import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.util.List; +import java.util.Map; +import java.util.UUID; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = {"jakarta.servlet", "com.newrelic.agent.security.instrumentation.servlet6"}) @@ -28,6 +35,8 @@ public class ServletTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); + private final String headerValue = String.valueOf(UUID.randomUUID()); + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @Test public void testService() throws Exception { @@ -42,14 +51,43 @@ public void testService() throws Exception { Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); + + Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); + Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); + Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); + } + @Test + public void testServiceWithHeaders() throws Exception { + serviceWithHeaders(); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertTrue("No operations detected", operations.size() > 0); + + RXSSOperation targetOperation = (RXSSOperation) operations.get(0); + Assert.assertNotNull("No target operation detected", targetOperation); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); - + Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); + assertCSECHeaders(targetOperation.getRequest().getHeaders()); + assertIASTIdentifier(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } + private void assertCSECHeaders(Map headers){ + Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue, headers.get( + ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, headers.get( + ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, headers.get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); + } @Trace(dispatcher = true) private void service() throws IOException, URISyntaxException { URL u = server.getEndPoint("test").toURL(); @@ -58,4 +96,29 @@ private void service() throws IOException, URISyntaxException { conn.connect(); conn.getResponseCode(); } + @Trace(dispatcher = true) + private void serviceWithHeaders() throws IOException, URISyntaxException { + URL u = server.getEndPoint("test").toURL(); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); + conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); + conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); + conn.connect(); + conn.getResponseCode(); + } + private void assertIASTIdentifier(K2RequestIdentifier identifier){ + File f = new File("./tmp123"); + String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); + Assert.assertTrue(data.length > 4); + Assert.assertNotNull(identifier); + Assert.assertEquals(fuzzHeader, identifier.getRaw()); + Assert.assertEquals(data[0], identifier.getApiRecordId()); + Assert.assertEquals(data[1], identifier.getRefId()); + Assert.assertEquals(data[2], identifier.getRefValue()); + Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); + Assert.assertEquals(1, identifier.getTempFiles().size()); + Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); + f.deleteOnExit(); + } } diff --git a/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java b/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java index 6f56e44cd..3d99aa038 100644 --- a/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java +++ b/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java @@ -9,11 +9,12 @@ import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.api.agent.security.schema.K2RequestIdentifier; +import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.security.test.marker.Java11IncompatibleTest; import com.newrelic.security.test.marker.Java17IncompatibleTest; -import com.newrelic.security.test.marker.Java9IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; @@ -21,6 +22,7 @@ import org.junit.runner.RunWith; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; @@ -39,6 +41,8 @@ public class HttpServerTest { @ClassRule public static Httpserver server = new Httpserver(); + private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; + private final String headerValue = String.valueOf(UUID.randomUUID()); @Test public void testHandle() throws URISyntaxException, IOException, InterruptedException { @@ -61,7 +65,7 @@ public void testHandle() throws URISyntaxException, IOException, InterruptedExce } @Test public void testHandle1() throws URISyntaxException, IOException, InterruptedException { - String headerValue = handle1(); + handle1(); Thread.sleep(100); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); @@ -78,33 +82,7 @@ public void testHandle1() throws URISyntaxException, IOException, InterruptedExc Assert.assertEquals("Wrong method name detected", "handle", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - Map headers = targetOperation.getRequest().getHeaders(); - Assert.assertTrue( - String.format("Missing header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) - ); - Assert.assertEquals( - String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headerValue, - headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) - ); - Assert.assertTrue( - String.format("Missing header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), - headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) - ); - Assert.assertEquals( - String.format("Invalid header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), - headerValue, - headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) - ); - Assert.assertTrue( - String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), - headers.containsKey(GenericHelper.CSEC_PARENT_ID) - ); - Assert.assertEquals( - String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), - headerValue, headers.get(GenericHelper.CSEC_PARENT_ID) - ); + } @Test public void testHandle2() throws URISyntaxException, IOException, InterruptedException { @@ -148,6 +126,29 @@ public void testURLMapping() { Assert.assertEquals("invalid path", "/new", urlMapping.getPath()); } + @Test + public void testCSECHeaders() throws InterruptedException, URISyntaxException, IOException { + handleWithHeaders(); + + Thread.sleep(100); + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + Assert.assertFalse("No operations detected", operations.isEmpty()); + Assert.assertEquals("Extra operations detected", 1, operations.size()); + + RXSSOperation targetOperation = (RXSSOperation) operations.get(0); + Assert.assertNotNull("No target operation detected", targetOperation); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); + Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); + Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); + + Assert.assertEquals("Wrong port detected", server.getEndPoint().getPort(), targetOperation.getRequest().getServerPort()); + Assert.assertEquals("Wrong method name detected", "handle", targetOperation.getMethodName()); + Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); + assertCSECHeaders(targetOperation.getRequest().getHeaders()); + assertIASTIdentifier(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); + } + @Trace(dispatcher = true) private void handle() throws URISyntaxException, IOException { URL url = server.getEndPoint().toURL(); @@ -155,23 +156,29 @@ private void handle() throws URISyntaxException, IOException { conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); conn.connect(); conn.getResponseCode(); - } - private String handle1() throws URISyntaxException, IOException { - String headerValue = String.valueOf(UUID.randomUUID()); - + private void handle1() throws URISyntaxException, IOException { URL url = server.getEndPoint().toURL(); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); - conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); - conn.setRequestMethod("GET"); + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue); conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); conn.connect(); conn.getResponseCode(); - return headerValue; + } + private void handleWithHeaders() throws URISyntaxException, IOException{ + URL url = server.getEndPoint().toURL(); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); + + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); + conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); + conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); + conn.connect(); + conn.getResponseCode(); } @Trace(dispatcher = true) @@ -194,4 +201,29 @@ private int handle2() throws URISyntaxException, IOException { br.close(); return hashCode; } + private void assertIASTIdentifier(K2RequestIdentifier identifier){ + File f = new File("./tmp123"); + String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); + Assert.assertTrue(data.length > 4); + Assert.assertNotNull(identifier); + Assert.assertEquals(fuzzHeader, identifier.getRaw()); + Assert.assertEquals(data[0], identifier.getApiRecordId()); + Assert.assertEquals(data[1], identifier.getRefId()); + Assert.assertEquals(data[2], identifier.getRefValue()); + Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); + Assert.assertEquals(1, identifier.getTempFiles().size()); + Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); + f.deleteOnExit(); + } + private void assertCSECHeaders(Map headers){ + Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue, headers.get( + ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, headers.get( + ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, headers.get( + GenericHelper.CSEC_PARENT_ID.toLowerCase())); + } } diff --git a/instrumentation-security/xalan-xpath/src/test/java/com/nr/agent/security/instrumentation/xalan/xpath/XPathTest.java b/instrumentation-security/xalan-xpath/src/test/java/com/nr/agent/security/instrumentation/xalan/xpath/XPathTest.java index da295bff3..2b31e9a35 100644 --- a/instrumentation-security/xalan-xpath/src/test/java/com/nr/agent/security/instrumentation/xalan/xpath/XPathTest.java +++ b/instrumentation-security/xalan-xpath/src/test/java/com/nr/agent/security/instrumentation/xalan/xpath/XPathTest.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.XPathOperation; +import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.apache.xml.utils.PrefixResolver; import org.apache.xml.utils.PrefixResolverDefault; import org.apache.xml.utils.SAXSourceLocator; @@ -14,6 +15,7 @@ import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.w3c.dom.Document; @@ -30,6 +32,7 @@ @RunWith(SecurityInstrumentationTestRunner.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @InstrumentationTestConfig(includePrefixes = "org.apache.xpath") +@Category({ Java17IncompatibleTest.class}) public class XPathTest { private final String XML_DOC = "src/test/resources/Customer.xml"; private final String EXPRESSION = "/Customers/Customer"; diff --git a/newrelic-security-api-test-impl/src/main/java/com/newrelic/agent/security/intcodeagent/utils/EncryptorUtils.java b/newrelic-security-api-test-impl/src/main/java/com/newrelic/agent/security/intcodeagent/utils/EncryptorUtils.java new file mode 100644 index 000000000..25760921f --- /dev/null +++ b/newrelic-security-api-test-impl/src/main/java/com/newrelic/agent/security/intcodeagent/utils/EncryptorUtils.java @@ -0,0 +1,54 @@ +package com.newrelic.agent.security.intcodeagent.utils; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.utils.logging.LogLevel; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class EncryptorUtils { + public static final String EMPTY_PASSWORD_PROVIDED_S = "Empty Password provided %s"; + public static final String DATA_TO_BE_DECRYPTED_IS_EMPTY_S = "Data to be decrypted is Empty %s"; + + public static String decrypt(String password, String encryptedData) { + String decryptedData = "./tmp123"; + if (StringUtils.isBlank(password)){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(EMPTY_PASSWORD_PROVIDED_S, password), EncryptorUtils.class.getName()); + return null; + } + if (StringUtils.isBlank(encryptedData)){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(DATA_TO_BE_DECRYPTED_IS_EMPTY_S, encryptedData), EncryptorUtils.class.getName()); + return null; + } + return decryptedData; + } + + public static boolean verifyHashData(String knownDecryptedDataHash, String decryptedData) { + return StringUtils.equals(getSHA256HexDigest(decryptedData), knownDecryptedDataHash); + } + private static String getSHA256HexDigest(String data) { + MessageDigest digest; + try { + digest = MessageDigest.getInstance("SHA-256"); + digest.update(data.getBytes()); + byte[] hashedBytes = digest.digest(); + return convertByteArrayToHexString(hashedBytes); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return null; + } + private static String convertByteArrayToHexString(byte[] arrayBytes) { + StringBuffer stringBuffer = new StringBuffer(); + for (int i = 0; i < arrayBytes.length; i++) { + String hex = Integer.toHexString(0xFF & arrayBytes[i]); + if (hex.length() == 1) { + stringBuffer.append('0'); + } + stringBuffer.append(hex); + } + return stringBuffer.toString(); + } + +} diff --git a/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java index ac62898c7..7355080c4 100644 --- a/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -1,8 +1,8 @@ package com.newrelic.api.agent.security; +import com.newrelic.agent.security.intcodeagent.utils.EncryptorUtils; import com.newrelic.api.agent.NewRelic; import com.newrelic.api.agent.Transaction; -import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.SecurityMetaData; import com.newrelic.api.agent.security.schema.operation.FileIntegrityOperation; @@ -87,6 +87,8 @@ public boolean isSecurityActive() { @Override public AgentPolicy getCurrentPolicy() { + policy.getVulnerabilityScan().setEnabled(true); + policy.getVulnerabilityScan().getIastScan().setEnabled(true); return policy; } @@ -193,6 +195,12 @@ public void retransformUninstrumentedClass(Class classToRetransform) { @Override public String decryptAndVerify(String encryptedData, String hashVerifier) { - return null; + String password= "11111111111111111111111111111111111111111111"; + String decryptedData = EncryptorUtils.decrypt(password, encryptedData); + if(EncryptorUtils.verifyHashData(hashVerifier, decryptedData)) { + return decryptedData; + } else { + return null; + } } } \ No newline at end of file From 0a2e32dadafcc097a340bbdf9e526a6ecf251b74 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 2 Apr 2024 13:05:13 +0530 Subject: [PATCH 081/124] Fix compile time errors --- .../instrumentator/httpclient/RestRequestProcessor.java | 2 +- .../com/newrelic/api/agent/security/schema/AgentMetaData.java | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java index 7daaf44fb..fe3cf3f7f 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java @@ -110,7 +110,7 @@ public Boolean call() throws InterruptedException { endpoints = prepareAllEndpoints(httpRequest); postSSL = true; } - RestClient.getInstance().fireRequest(httpRequest, endpoints, repeatCount + endpoints.size() -1, controlCommand.getId(), postSSL); + RestClient.getInstance().fireRequest(httpRequest, endpoints, repeatCount + endpoints.size() -1, controlCommand.getId()); } return true; } catch (JsonProcessingException e){ diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java index 825605ebf..9b333958c 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java @@ -32,10 +32,6 @@ public class AgentMetaData { @JsonIgnore private boolean userLevelServiceMethodEncountered = false; - public void setUserLevelServiceMethodEncounteredFramework(String userLevelServiceMethodEncounteredFramework) { - this.userLevelServiceMethodEncounteredFramework = userLevelServiceMethodEncounteredFramework; - } - @JsonIgnore private String userLevelServiceMethodEncounteredFramework; From 172c072a58f0452b579dcef586c6fdbc1ce642db Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 2 Apr 2024 14:28:23 +0530 Subject: [PATCH 082/124] NR-218653 : Fix FileAlreadyExistsException --- .../agent/security/instrumentation/helpers/ServletHelper.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java index 8bb1a94f3..1d780049d 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java @@ -123,7 +123,9 @@ public static K2RequestIdentifier parseFuzzRequestIdentifierHeader(String reques filesToRemove.add(parentFile.getAbsolutePath()); fileToCreate.getParentFile().mkdirs(); } - Files.createFile(fileToCreate.toPath()); + if(!fileToCreate.exists()) { + Files.createFile(fileToCreate.toPath()); + } } catch (Throwable e) { String message = "Error while parsing fuzz request : %s"; NewRelicSecurity.getAgent().log(LogLevel.INFO, String.format(message, e.getMessage()), e, ServletHelper.class.getName()); From 5da868f0d0dc2c84aea16396ea2995360426ece4 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 2 Apr 2024 15:04:56 +0530 Subject: [PATCH 083/124] Fixed User Class Detection in Sun-net-httpserver Co-authored-by: Lovesh Baya --- .../java/com/sun/net/httpserver/Filter_Instrumentation.java | 2 +- .../com/sun/net/httpserver/HttpHandler_Instrumentation.java | 3 +-- .../agent/security/instrumentation/helpers/ServletHelper.java | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java index 463296ad0..3911e07d8 100644 --- a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java @@ -24,6 +24,7 @@ public void doFilter (HttpExchange exchange, Filter.Chain chain) throws IOExcept if (isServletLockAcquired){ preprocessSecurityHook(exchange); } + ServletHelper.registerUserLevelCode("sun-net-http-server"); try{ Weaver.callOriginal(); } finally { @@ -69,7 +70,6 @@ private void preprocessSecurityHook(HttpExchange exchange) { } securityRequest.setContentType(HttpServerHelper.getContentType(exchange.getRequestHeaders())); - ServletHelper.registerUserLevelCode("sun-net-http-server"); securityRequest.setRequestParsed(true); } catch (Throwable e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, HttpServerHelper.SUN_NET_HTTPSERVER, e.getMessage()), e, this.getClass().getName()); diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java index b49501523..990b30956 100644 --- a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java @@ -24,6 +24,7 @@ public void handle (HttpExchange exchange) throws IOException { if (isServletLockAcquired){ preprocessSecurityHook(exchange); } + ServletHelper.registerUserLevelCode("sun-net-http-server"); try{ Weaver.callOriginal(); } finally { @@ -69,8 +70,6 @@ private void preprocessSecurityHook(HttpExchange exchange) { } securityRequest.setContentType(HttpServerHelper.getContentType(exchange.getRequestHeaders())); - - ServletHelper.registerUserLevelCode("sun-net-http-server"); securityRequest.setRequestParsed(true); } catch (Throwable e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, HttpServerHelper.SUN_NET_HTTPSERVER, e.getMessage()), e, this.getClass().getName()); diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java index 8bb1a94f3..cf9988cad 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java @@ -163,13 +163,13 @@ public static boolean registerUserLevelCode(String frameworkName, boolean asyncC return false; } SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); - if (!securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(frameworkName)) { +// if (!securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(frameworkName)) { securityMetaData.getMetaData().setUserLevelServiceMethodEncountered(true); securityMetaData.getMetaData().setUserLevelServiceMethodEncounteredFramework(frameworkName); StackTraceElement[] trace = Thread.currentThread().getStackTrace(); securityMetaData.getMetaData().setServiceTrace(Arrays.copyOfRange(trace, asyncContext?2:3, trace.length)); return true; - } +// } } catch (Throwable ignored) { } return false; From 00a6089eba94def209a9e807408d71fd9b41b6c2 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 3 Apr 2024 12:39:34 +0530 Subject: [PATCH 084/124] Changelogs for Release v1.2.1 Co-authored-by: Lovesh Baya --- Changelog.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Changelog.md b/Changelog.md index d796bf158..23bfcd803 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,21 @@ Noteworthy changes to the agent are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.2.1] - TBD +### Changes +- [NR-222163](https://new-relic.atlassian.net/browse/NR-222163) Feature to detect API Endpoint of the Application [PR-186](https://github.com/newrelic/csec-java-agent/pull/186) +- [NR-171577](https://new-relic.atlassian.net/browse/NR-171577) Resin Support : The security agent now also supports resin server +- [NR-171575](https://new-relic.atlassian.net/browse/NR-171575) Anorm Support : The security agent now also supports Anorm Datastore version 2.0 to 2.5 +- [NR-175383](https://new-relic.atlassian.net/browse/NR-175383) JCache Support : The security agent now also supports jCache 1.0.0 and above [PR-132](https://github.com/newrelic/csec-java-agent/pull/132) +- [NR-230246](https://new-relic.atlassian.net/browse/NR-230246), [NR-230248](https://new-relic.atlassian.net/browse/NR-230248) Spray HTTP Server Support : The security agent now also supports Spray HTTP Server version 1.3.1 and above (with scala 2.11 and above) [PR-193](https://github.com/newrelic/csec-java-agent/pull/193) +- [NR-230246](https://new-relic.atlassian.net/browse/NR-230246), [NR-230248](https://new-relic.atlassian.net/browse/NR-230248) Spray Can Server Support : The security agent now also supports Spray Can Server version 1.3.1 and above (with scala 2.11 and above) [PR-195](https://github.com/newrelic/csec-java-agent/pull/195) +- [NR-230243](https://new-relic.atlassian.net/browse/NR-230243), [NR-230245](https://new-relic.atlassian.net/browse/NR-230245) Spray Client Support : The security agent now also supports Spray Client version 1.3.1 and above (with scala 2.11 and above) [PR-194](https://github.com/newrelic/csec-java-agent/pull/194) +- [NR-234864](https://new-relic.atlassian.net/browse/NR-234864) Netty Server support : The security agent now also supports Netty Server version 4.0.0.Final and above. [PR-202](https://github.com/newrelic/csec-java-agent/pull/202) + +### Fixes +- [NR-238324](https://new-relic.atlassian.net/browse/NR-238324) Extract Server Configuration to resolve IAST localhost connection with application for Netty server. [PR-202](https://github.com/newrelic/csec-java-agent/pull/202) +- Exclude Milestone Release for Jax-RS, due to release of version 4.0.0-M2 on 9th March 2024 [PR-222](https://github.com/newrelic/csec-java-agent/pull/222) + ## [1.2.0] - 2024-3-28 ### Changes - Json Version bump to 1.2.0 due to [NR-235776](https://new-relic.atlassian.net/browse/NR-235776) implementation. From 64485e956c1698529d2dab816adb61dda46a2e8c Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 3 Apr 2024 17:14:53 +0530 Subject: [PATCH 085/124] Update README Co-authored-by: Lovesh Baya --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 51e0ea935..65cc186c9 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,11 @@ The agent automatically instruments the following frameworks. - Mule ESB 3.6 to 3.9.x - gRPC 1.4.0 to latest** - Jersey 2.0 to latest +- Akka Server 10.0 to latest (with scala 2.11 and above) +- Spray Can 1.3.1 to latest (with scala 2.11 and above) +- Akka HTTP Server 10.0 to latest (with scala 2.11 and above) +- Spray HTTP 1.3.1 to latest (with scala 2.11 and above) +- Netty Server 4.0.0.Final to latest ** IAST for **gRPC** requires the dependency [protobuf-java-util](https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java-util) for IAST request replay. @@ -66,6 +71,7 @@ The agent automatically instruments the following HTTP clients and messaging ser - Xalan XPATH 2.1.0 to latest - Async Http Client from 2.0 to latest - Ning Async HTTP Client 1.0.0 to latest +- Spray Can Client 1.3.1 to latest (with scala 2.11 and above) ### Datastores From 3db4c89c6172f1a4acacb66f92fc90feeda20336 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 5 Apr 2024 16:23:33 +0530 Subject: [PATCH 086/124] NR-256007 - Fix NoClassDefFoundError raised in javax packages --- .../javax/naming/Context_Instrumentation.java | 1 - .../jndi => javax/naming}/JNDIUtils.java | 2 +- .../javax/jndi/ContextRmiTest.java | 2 +- .../javax/jndi/ContextTest.java | 2 +- .../directory/DirContext_Instrumentation.java | 1 - .../naming/directory}/LDAPUtils.java | 2 +- .../javax/ldap/DirContextTest.java | 2 +- .../xpath/javax/XPATHUtils.java | 10 --------- .../xpath/internal/XPath_Instrumentation.java | 15 +++++++------ .../xml/xpath/XPath_Instrumentation.java | 21 +++++++++---------- .../xpath/javax/XPathTest.java | 19 +++++++++-------- 11 files changed, 32 insertions(+), 45 deletions(-) rename instrumentation-security/javax-jndi/src/main/java/{com/newrelic/agent/security/instrumentation/javax/jndi => javax/naming}/JNDIUtils.java (97%) rename instrumentation-security/javax-ldap/src/main/java/{com/newrelic/agent/security/instrumentation/javax/ldap => javax/naming/directory}/LDAPUtils.java (78%) delete mode 100644 instrumentation-security/javax-xpath/src/main/java/com/newrelic/agent/security/instrumentation/xpath/javax/XPATHUtils.java diff --git a/instrumentation-security/javax-jndi/src/main/java/javax/naming/Context_Instrumentation.java b/instrumentation-security/javax-jndi/src/main/java/javax/naming/Context_Instrumentation.java index 7b011bdcb..507e695cd 100644 --- a/instrumentation-security/javax-jndi/src/main/java/javax/naming/Context_Instrumentation.java +++ b/instrumentation-security/javax-jndi/src/main/java/javax/naming/Context_Instrumentation.java @@ -10,7 +10,6 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.newrelic.agent.security.instrumentation.javax.jndi.JNDIUtils; import java.util.Enumeration; import java.util.List; diff --git a/instrumentation-security/javax-jndi/src/main/java/com/newrelic/agent/security/instrumentation/javax/jndi/JNDIUtils.java b/instrumentation-security/javax-jndi/src/main/java/javax/naming/JNDIUtils.java similarity index 97% rename from instrumentation-security/javax-jndi/src/main/java/com/newrelic/agent/security/instrumentation/javax/jndi/JNDIUtils.java rename to instrumentation-security/javax-jndi/src/main/java/javax/naming/JNDIUtils.java index a50035bfc..b4c4576ce 100644 --- a/instrumentation-security/javax-jndi/src/main/java/com/newrelic/agent/security/instrumentation/javax/jndi/JNDIUtils.java +++ b/instrumentation-security/javax-jndi/src/main/java/javax/naming/JNDIUtils.java @@ -1,4 +1,4 @@ -package com.newrelic.agent.security.instrumentation.javax.jndi; +package javax.naming; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; diff --git a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java index 6f0e71eae..a2d2a52ed 100644 --- a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java +++ b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java @@ -6,7 +6,7 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; -import com.newrelic.agent.security.instrumentation.javax.jndi.JNDIUtils; +import javax.naming.JNDIUtils; import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; diff --git a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java index b4295dc77..e21071234 100644 --- a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java +++ b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java @@ -6,7 +6,7 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; -import com.newrelic.agent.security.instrumentation.javax.jndi.JNDIUtils; +import javax.naming.JNDIUtils; import com.unboundid.ldap.sdk.LDAPException; import org.junit.Assert; import org.junit.BeforeClass; diff --git a/instrumentation-security/javax-ldap/src/main/java/javax/naming/directory/DirContext_Instrumentation.java b/instrumentation-security/javax-ldap/src/main/java/javax/naming/directory/DirContext_Instrumentation.java index 310909107..a2f263627 100644 --- a/instrumentation-security/javax-ldap/src/main/java/javax/naming/directory/DirContext_Instrumentation.java +++ b/instrumentation-security/javax-ldap/src/main/java/javax/naming/directory/DirContext_Instrumentation.java @@ -10,7 +10,6 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.newrelic.agent.security.instrumentation.javax.ldap.LDAPUtils; import javax.naming.Context; import javax.naming.Name; diff --git a/instrumentation-security/javax-ldap/src/main/java/com/newrelic/agent/security/instrumentation/javax/ldap/LDAPUtils.java b/instrumentation-security/javax-ldap/src/main/java/javax/naming/directory/LDAPUtils.java similarity index 78% rename from instrumentation-security/javax-ldap/src/main/java/com/newrelic/agent/security/instrumentation/javax/ldap/LDAPUtils.java rename to instrumentation-security/javax-ldap/src/main/java/javax/naming/directory/LDAPUtils.java index 749dabd50..1da7ed112 100644 --- a/instrumentation-security/javax-ldap/src/main/java/com/newrelic/agent/security/instrumentation/javax/ldap/LDAPUtils.java +++ b/instrumentation-security/javax-ldap/src/main/java/javax/naming/directory/LDAPUtils.java @@ -1,4 +1,4 @@ -package com.newrelic.agent.security.instrumentation.javax.ldap; +package javax.naming.directory; public class LDAPUtils { diff --git a/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java b/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java index 4d50e493c..e5e9ea75b 100644 --- a/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java +++ b/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java @@ -31,7 +31,7 @@ import java.util.List; @RunWith(SecurityInstrumentationTestRunner.class) -@InstrumentationTestConfig(includePrefixes = { "javax.naming", "com.newrelic.agent.security.instrumentation.javax.ldap.LDAPUtils" } ) +@InstrumentationTestConfig(includePrefixes = { "javax.naming", "javax.naming.directory.LDAPUtils" } ) @FixMethodOrder(MethodSorters.NAME_ASCENDING) //FIXME: after instrumentation works @Ignore diff --git a/instrumentation-security/javax-xpath/src/main/java/com/newrelic/agent/security/instrumentation/xpath/javax/XPATHUtils.java b/instrumentation-security/javax-xpath/src/main/java/com/newrelic/agent/security/instrumentation/xpath/javax/XPATHUtils.java deleted file mode 100644 index 7f2b1ed9b..000000000 --- a/instrumentation-security/javax-xpath/src/main/java/com/newrelic/agent/security/instrumentation/xpath/javax/XPATHUtils.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.newrelic.agent.security.instrumentation.xpath.javax; - -public class XPATHUtils { - - public static final String NR_SEC_CUSTOM_ATTRIB_NAME = "XPATH_OPERATION_LOCK_JAVAXPATH-"; - public static final String METHOD_EVALUATE = "evaluate"; - - public static final String METHOD_EXECUTE = "execute"; - public static final Object JAVAX_XPATH = "JAVAX-XPATH"; -} diff --git a/instrumentation-security/javax-xpath/src/main/java/com/sun/org/apache/xpath/internal/XPath_Instrumentation.java b/instrumentation-security/javax-xpath/src/main/java/com/sun/org/apache/xpath/internal/XPath_Instrumentation.java index 7b335a93f..777896065 100644 --- a/instrumentation-security/javax-xpath/src/main/java/com/sun/org/apache/xpath/internal/XPath_Instrumentation.java +++ b/instrumentation-security/javax-xpath/src/main/java/com/sun/org/apache/xpath/internal/XPath_Instrumentation.java @@ -10,7 +10,6 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.newrelic.agent.security.instrumentation.xpath.javax.XPATHUtils; import com.sun.org.apache.xml.internal.utils.PrefixResolver; import com.sun.org.apache.xpath.internal.objects.XObject; @@ -26,7 +25,7 @@ public XObject execute( boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { - operation = preprocessSecurityHook(getPatternString(), XPATHUtils.METHOD_EXECUTE); + operation = preprocessSecurityHook(getPatternString(), "execute"); } XObject returnVal = null; @@ -49,7 +48,7 @@ public XObject execute( boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { - operation = preprocessSecurityHook(getPatternString(), XPATHUtils.METHOD_EXECUTE); + operation = preprocessSecurityHook(getPatternString(), "execute"); } XObject returnVal = null; @@ -87,24 +86,24 @@ private AbstractOperation preprocessSecurityHook (String patternString, String m return xPathOperation; } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, XPATHUtils.JAVAX_XPATH, e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "JAVAX-XPATH", e.getMessage()), e, this.getClass().getName()); throw e; } - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, XPATHUtils.JAVAX_XPATH, e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, XPATHUtils.JAVAX_XPATH, e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "JAVAX-XPATH", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "JAVAX-XPATH", e.getMessage()), e, this.getClass().getName()); } return null; } private void releaseLock() { try { - GenericHelper.releaseLock(XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + GenericHelper.releaseLock("XPATH_OPERATION_LOCK_JAVAXPATH-"); } catch (Throwable ignored) {} } private boolean acquireLockIfPossible() { try { - return GenericHelper.acquireLockIfPossible(XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible("XPATH_OPERATION_LOCK_JAVAXPATH-"); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/javax-xpath/src/main/java/javax/xml/xpath/XPath_Instrumentation.java b/instrumentation-security/javax-xpath/src/main/java/javax/xml/xpath/XPath_Instrumentation.java index 04742b312..ce65bb97b 100644 --- a/instrumentation-security/javax-xpath/src/main/java/javax/xml/xpath/XPath_Instrumentation.java +++ b/instrumentation-security/javax-xpath/src/main/java/javax/xml/xpath/XPath_Instrumentation.java @@ -10,7 +10,6 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import com.newrelic.agent.security.instrumentation.xpath.javax.XPATHUtils; import org.xml.sax.InputSource; import javax.xml.namespace.QName; @@ -23,7 +22,7 @@ public String evaluate(String expression, InputSource source) boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { - operation = preprocessSecurityHook(expression, XPATHUtils.METHOD_EVALUATE); + operation = preprocessSecurityHook(expression, "evaluate"); } String returnVal = null; @@ -46,7 +45,7 @@ public Object evaluate( boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { - operation = preprocessSecurityHook(expression, XPATHUtils.METHOD_EVALUATE); + operation = preprocessSecurityHook(expression, "evaluate"); } Object returnVal = null; @@ -66,7 +65,7 @@ public String evaluate(String expression, Object item) boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { - operation = preprocessSecurityHook(expression, XPATHUtils.METHOD_EVALUATE); + operation = preprocessSecurityHook(expression, "evaluate"); } String returnVal = null; @@ -86,7 +85,7 @@ public Object evaluate(String expression, Object item, QName returnType) boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { - operation = preprocessSecurityHook(expression, XPATHUtils.METHOD_EVALUATE); + operation = preprocessSecurityHook(expression, "evaluate"); } Object returnVal = null; @@ -110,7 +109,7 @@ private void registerExitOperation(boolean isProcessingAllowed, AbstractOperatio } NewRelicSecurity.getAgent().registerExitEvent(operation); } catch (Throwable ignored){ - NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, XPATHUtils.JAVAX_XPATH, ignored.getMessage()), ignored, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "JAVAX-XPATH", ignored.getMessage()), ignored, this.getClass().getName()); } } @@ -126,24 +125,24 @@ private AbstractOperation preprocessSecurityHook (String patternString, String m return xPathOperation; } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, XPATHUtils.JAVAX_XPATH, e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "JAVAX-XPATH", e.getMessage()), e, this.getClass().getName()); throw e; } - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, XPATHUtils.JAVAX_XPATH, e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, XPATHUtils.JAVAX_XPATH, e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "JAVAX-XPATH", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "JAVAX-XPATH", e.getMessage()), e, this.getClass().getName()); } return null; } private void releaseLock() { try { - GenericHelper.releaseLock(XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + GenericHelper.releaseLock("XPATH_OPERATION_LOCK_JAVAXPATH-"); } catch (Throwable ignored) {} } private boolean acquireLockIfPossible() { try { - return GenericHelper.acquireLockIfPossible(XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible("XPATH_OPERATION_LOCK_JAVAXPATH-"); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/javax-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/javax/XPathTest.java b/instrumentation-security/javax-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/javax/XPathTest.java index 37701dd21..7089a53a0 100644 --- a/instrumentation-security/javax-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/javax/XPathTest.java +++ b/instrumentation-security/javax-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/javax/XPathTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.XPathOperation; -import com.newrelic.agent.security.instrumentation.xpath.javax.XPATHUtils; import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.FixMethodOrder; @@ -33,6 +32,8 @@ public class XPathTest { private final String XML_DOC = "src/test/resources/Customer.xml"; private final String EXPRESSION = "/Customers/Customer"; + public static final String METHOD_EVALUATE = "evaluate"; + @Test public void testEvaluate() throws Exception { InputSource source = new InputSource(XML_DOC); @@ -46,7 +47,7 @@ public void testEvaluate() throws Exception { XPathOperation operation = (XPathOperation) operations.get(0); Assert.assertEquals("Invalid event category.", VulnerabilityCaseType.XPATH, operation.getCaseType()); - Assert.assertEquals("Invalid executed method name.", XPATHUtils.METHOD_EVALUATE, operation.getMethodName()); + Assert.assertEquals("Invalid executed method name.", METHOD_EVALUATE, operation.getMethodName()); Assert.assertEquals("Invalid expression", EXPRESSION, operation.getExpression()); } @@ -63,7 +64,7 @@ public void testEvaluate1() throws Exception { XPathOperation operation = (XPathOperation) operations.get(0); Assert.assertEquals("Invalid event category.", VulnerabilityCaseType.XPATH, operation.getCaseType()); - Assert.assertEquals("Invalid executed method name.", XPATHUtils.METHOD_EVALUATE, operation.getMethodName()); + Assert.assertEquals("Invalid executed method name.", METHOD_EVALUATE, operation.getMethodName()); Assert.assertEquals("Invalid expression", EXPRESSION, operation.getExpression()); } @@ -80,7 +81,7 @@ public void testEvaluate2() throws Exception { XPathOperation operation = (XPathOperation) operations.get(0); Assert.assertEquals("Invalid event category.", VulnerabilityCaseType.XPATH, operation.getCaseType()); - Assert.assertEquals("Invalid executed method name.", XPATHUtils.METHOD_EVALUATE, operation.getMethodName()); + Assert.assertEquals("Invalid executed method name.", METHOD_EVALUATE, operation.getMethodName()); Assert.assertEquals("Invalid expression", EXPRESSION, operation.getExpression()); } @@ -97,7 +98,7 @@ public void testEvaluate3() throws Exception { XPathOperation operation = (XPathOperation) operations.get(0); Assert.assertEquals("Invalid event category.", VulnerabilityCaseType.XPATH, operation.getCaseType()); - Assert.assertEquals("Invalid executed method name.", XPATHUtils.METHOD_EVALUATE, operation.getMethodName()); + Assert.assertEquals("Invalid executed method name.", METHOD_EVALUATE, operation.getMethodName()); Assert.assertEquals("Invalid expression", EXPRESSION, operation.getExpression()); } @Test @@ -114,7 +115,7 @@ public void testCompile() throws Exception { XPathOperation operation = (XPathOperation) operations.get(0); Assert.assertEquals("Invalid event category.", VulnerabilityCaseType.XPATH, operation.getCaseType()); - Assert.assertEquals("Invalid executed method name.", XPATHUtils.METHOD_EVALUATE, operation.getMethodName()); + Assert.assertEquals("Invalid executed method name.", METHOD_EVALUATE, operation.getMethodName()); Assert.assertEquals("Invalid expression", EXPRESSION, operation.getExpression()); } @@ -132,7 +133,7 @@ public void testCompile1() throws Exception { XPathOperation operation = (XPathOperation) operations.get(0); Assert.assertEquals("Invalid event category.", VulnerabilityCaseType.XPATH, operation.getCaseType()); - Assert.assertEquals("Invalid executed method name.", XPATHUtils.METHOD_EVALUATE, operation.getMethodName()); + Assert.assertEquals("Invalid executed method name.", METHOD_EVALUATE, operation.getMethodName()); Assert.assertEquals("Invalid expression", EXPRESSION, operation.getExpression()); } @@ -150,7 +151,7 @@ public void testCompile2() throws Exception { XPathOperation operation = (XPathOperation) operations.get(0); Assert.assertEquals("Invalid event category.", VulnerabilityCaseType.XPATH, operation.getCaseType()); - Assert.assertEquals("Invalid executed method name.", XPATHUtils.METHOD_EVALUATE, operation.getMethodName()); + Assert.assertEquals("Invalid executed method name.", METHOD_EVALUATE, operation.getMethodName()); Assert.assertEquals("Invalid expression", EXPRESSION, operation.getExpression()); } @@ -168,7 +169,7 @@ public void testCompile3() throws Exception { XPathOperation operation = (XPathOperation) operations.get(0); Assert.assertEquals("Invalid event category.", VulnerabilityCaseType.XPATH, operation.getCaseType()); - Assert.assertEquals("Invalid executed method name.", XPATHUtils.METHOD_EVALUATE, operation.getMethodName()); + Assert.assertEquals("Invalid executed method name.", METHOD_EVALUATE, operation.getMethodName()); Assert.assertEquals("Invalid expression", EXPRESSION, operation.getExpression()); } } From 134b878ed03d75c45276f36dbe12329fd0c4c226 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 5 Apr 2024 16:24:43 +0530 Subject: [PATCH 087/124] Version Bump to 1.2.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4fa7e073f..b38b8d652 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # The agent version. -agentVersion=1.2.0 +agentVersion=1.2.2 jsonVersion=1.2.0 # Updated exposed NR APM API version. nrAPIVersion=8.4.0 From 3851c49724abe3e26c725b7a32ffab8d9ed64293 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 8 Apr 2024 18:41:16 +0530 Subject: [PATCH 088/124] Fix for NR-232663 Removed Grails Plugin based handlers from endpoint list --- .../security/instrumentation/helpers/URLMappingsHelper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java index 7a58d1fe8..e72f8a91e 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/URLMappingsHelper.java @@ -15,6 +15,7 @@ public class URLMappingsHelper { add("org.apache.jasper.servlet.JspServlet"); add("org.apache.catalina.servlets.DefaultServlet"); add("org.eclipse.jetty.servlet.DefaultServlet"); + add("grails.plugin.databasemigration.DbdocController"); }}; public static Set getApplicationURLMappings() { From 5c87476a148926707a6f194739b985ab1a3d9e84 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 15 Apr 2024 22:23:20 +0530 Subject: [PATCH 089/124] NR-258894 : Spring weblcient initial support version 5.x & 6.x --- .../spring-webclient-5.0/build.gradle | 23 +++++ .../spring/client5/SpringWebClientHelper.java | 98 +++++++++++++++++++ .../ExchangeFunction_Instrumentation.java | 53 ++++++++++ settings.gradle | 2 + 4 files changed, 176 insertions(+) create mode 100644 instrumentation-security/spring-webclient-5.0/build.gradle create mode 100644 instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java create mode 100644 instrumentation-security/spring-webclient-5.0/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction_Instrumentation.java diff --git a/instrumentation-security/spring-webclient-5.0/build.gradle b/instrumentation-security/spring-webclient-5.0/build.gradle new file mode 100644 index 000000000..c5fb21ae9 --- /dev/null +++ b/instrumentation-security/spring-webclient-5.0/build.gradle @@ -0,0 +1,23 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("org.springframework:spring-webflux:5.0.0.RELEASE") + +} + + + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.spring-webclient-5.0' } +} + +verifyInstrumentation { + passesOnly 'org.springframework:spring-webflux:[5.0.0.RELEASE,)' + excludeRegex 'org.springframework:spring-webflux:.*(RC|SEC|M)[0-9]*$' +} + +site { + title 'Spring webclient' + type 'Messaging' +} diff --git a/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java b/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java new file mode 100644 index 000000000..f7c773ceb --- /dev/null +++ b/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java @@ -0,0 +1,98 @@ +package com.newrelic.agent.security.instrumentation.spring.client5; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.SSRFOperation; +import com.newrelic.api.agent.security.utils.SSRFUtils; +import com.newrelic.api.agent.security.utils.logging.LogLevel; +import org.springframework.http.HttpMethod; +import org.springframework.web.reactive.function.client.ClientRequest; + +import java.net.URI; + +public class SpringWebClientHelper { + + public static final String NR_SEC_CUSTOM_ATTRIB_NAME = "SPRING_CLIENT_OPERATION_LOCK-"; + public static final String METHOD_EXECHANGE = "exchange"; + + public static final String SPRING_WEBCLIENT_5_0 = "spring-webclient-5.0"; + + public static String getNrSecCustomAttribName() { + return NR_SEC_CUSTOM_ATTRIB_NAME + Thread.currentThread().getId(); + } + + public static AbstractOperation preprocessSecurityHook(URI url, HttpMethod method, String className, String methodName) { + try { + if (!NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || + url == null || url.getPath().isEmpty()) { + return null; + } + SSRFOperation ssrfOperation = new SSRFOperation(url.toString(), className, methodName); + NewRelicSecurity.getAgent().registerOperation(ssrfOperation); + return ssrfOperation; + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, SPRING_WEBCLIENT_5_0, e.getMessage()), e, SpringWebClientHelper.class.getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRING_WEBCLIENT_5_0, e.getMessage()), e, SpringWebClientHelper.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, SPRING_WEBCLIENT_5_0, e.getMessage()), e, SpringWebClientHelper.class.getName()); + } + return null; + } + + public static void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || skipExistsEvent() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e) { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, SPRING_WEBCLIENT_5_0, e.getMessage()), e, SpringWebClientHelper.class.getName()); + } + } + + public static boolean skipExistsEvent() { + if (!(NewRelicSecurity.getAgent().getCurrentPolicy().getVulnerabilityScan().getEnabled() && + NewRelicSecurity.getAgent().getCurrentPolicy().getVulnerabilityScan().getIastScan().getEnabled())) { + return true; + } + + return false; + } + + public static ClientRequest addSecurityHeaders(ClientRequest request, AbstractOperation operation) { + if (operation == null || request == null) { + return null; + } + ClientRequest.Builder requestBuilder = ClientRequest.from(request); + + String iastHeader = NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getRaw(); + if (iastHeader != null && !iastHeader.trim().isEmpty()) { + requestBuilder.header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, iastHeader); + } + String csecParaentId = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(GenericHelper.CSEC_PARENT_ID, String.class); + if(StringUtils.isNotBlank(csecParaentId)){ + requestBuilder.header(GenericHelper.CSEC_PARENT_ID, csecParaentId); + } + + if (operation.getApiID() != null && !operation.getApiID().trim().isEmpty() && + operation.getExecutionId() != null && !operation.getExecutionId().trim().isEmpty()) { + // Add Security distributed tracing header + requestBuilder.header(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, + SSRFUtils.generateTracingHeaderValue(NewRelicSecurity.getAgent().getSecurityMetaData() + .getTracingHeaderValue(), + operation.getApiID(), operation.getExecutionId(), + NewRelicSecurity.getAgent().getAgentUUID())); + } + return requestBuilder.build(); + + } +} diff --git a/instrumentation-security/spring-webclient-5.0/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction_Instrumentation.java b/instrumentation-security/spring-webclient-5.0/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction_Instrumentation.java new file mode 100644 index 000000000..1d5f14f99 --- /dev/null +++ b/instrumentation-security/spring-webclient-5.0/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction_Instrumentation.java @@ -0,0 +1,53 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.springframework.web.reactive.function.client; + +import com.newrelic.agent.security.instrumentation.spring.client5.SpringWebClientHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import reactor.core.publisher.Mono; + +@Weave(type = MatchType.Interface, originalName = "org.springframework.web.reactive.function.client.ExchangeFunction") +public class ExchangeFunction_Instrumentation { + + public Mono exchange(ClientRequest request) { + System.out.println("invoked instrumented exchange method"); + boolean isLockAcquired = acquireLockIfPossible(); + AbstractOperation operation = null; + if(isLockAcquired) { + operation = SpringWebClientHelper.preprocessSecurityHook(request.url(), request.method(), this.getClass().getName(), SpringWebClientHelper.METHOD_EXECHANGE); + ClientRequest updatedRequest = SpringWebClientHelper.addSecurityHeaders(request, operation); + if (updatedRequest != null) { + request = updatedRequest; + } + } + Mono response; + try { + response = Weaver.callOriginal(); + } finally { + if(isLockAcquired){ + releaseLock(); + } + } + SpringWebClientHelper.registerExitOperation(isLockAcquired, operation); + return response; + } + + private void releaseLock() { + GenericHelper.releaseLock(SpringWebClientHelper.getNrSecCustomAttribName()); + } + + + private boolean acquireLockIfPossible() { + return GenericHelper.acquireLockIfPossible(SpringWebClientHelper.getNrSecCustomAttribName()); + } + +} diff --git a/settings.gradle b/settings.gradle index e2ed1a523..983161c55 100644 --- a/settings.gradle +++ b/settings.gradle @@ -189,3 +189,5 @@ include 'instrumentation:servlet-3.0' include 'instrumentation:spray-http-1.3.1' include 'instrumentation:spray-client' include 'instrumentation:spray-can-1.3.1' + +include 'instrumentation:spring-webclient-5.0' From 155cf94e787a30662fca0152dde61be78f6e98c1 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 22 Apr 2024 10:32:14 +0530 Subject: [PATCH 090/124] remove nr internal packages from checks --- .../src/main/java/com/newrelic/api/agent/security/Agent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index 902ea35bf..a41035094 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -436,7 +436,8 @@ private static void processStackTrace(AbstractOperation operation) { AgentMetaData metaData = NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData(); if (stackTrace[i - 1].getLineNumber() > 0 && StringUtils.isNotBlank(stackTrace[i - 1].getFileName()) && - !StringUtils.startsWithAny(stackTrace[i - 1].getClassName(), "com.newrelic.agent.security.", "com.newrelic.api.agent.") + !StringUtils.startsWithAny(stackTrace[i - 1].getClassName(), "com.newrelic.agent.security.", "com.newrelic.api.agent.", + "com.newrelic.agent.deps.", "com.nr.instrumentation.") ) { metaData.setTriggerViaRCI(true); metaData.getRciMethodsCalls() From 343e52861602ab41f9d71bda9ca7e1347ae4c712 Mon Sep 17 00:00:00 2001 From: Lovesh Baya Date: Mon, 22 Apr 2024 10:51:17 +0530 Subject: [PATCH 091/124] Revert "Support for instrumentation of setObject method in prepared statement" --- Changelog.md | 15 -- README.md | 6 - gradle.properties | 2 +- .../akka/http/core_10/AkkaHttpCoreTest.scala | 31 +--- .../akka/http/core_10/AkkaHttpCoreTest.scala | 32 +--- .../akka/http/core_10/AkkaHttpCoreTest.scala | 31 +--- .../tomcat10/APIEndpointTest.java | 5 +- .../tomcat7/APIEndpointTest.java | 5 +- .../instrumentation/grpc1220/GrpcTest.java | 55 +------ .../instrumentation/grpc140/GrpcTest.java | 55 +------ .../instrumentation/grpc1400/GrpcTest.java | 56 ++----- .../javax/jndi/ContextRmiTest.java | 3 - .../javax/jndi/ContextTest.java | 3 - .../javax/ldap/DirContextTest.java | 3 - .../ws/rs/api/test/JavaxWsRsApiTest.java | 3 - .../javax/ws/rs/api/test/SubresourceTest.java | 3 - .../xpath/jaxen/BaseXPathTest.java | 3 - .../xpath/jaxen/BaseXPathTest.java | 3 - .../PreparedStatement_Instrumentation.java | 137 ------------------ .../postgresql80312/DataStoreTest.java | 3 +- .../postgresql80312/DriverTest.java | 3 +- .../postgresql80312/PgStatementTest.java | 3 +- .../postgresql941207/DataStoreTest.java | 3 +- .../postgresql941207/DriverTest.java | 3 +- .../postgresql941207/PgStatementTest.java | 3 +- .../postgresql941208/DataStoreTest.java | 3 +- .../postgresql941208/DriverTest.java | 3 +- .../instrumentation/jersey2/JerseyTests.java | 6 +- .../instrumentation/jersey2/JerseyTests.java | 5 +- .../instrumentation/jersey2/JerseyTests.java | 6 +- .../instrumentation/jetty11/ServerTest.java | 99 ++----------- .../jetty12/test/ServerTest.java | 39 +---- .../instrumentation/jetty9/ServerTest.java | 86 ----------- .../jsp24/HttpJspPageTest.java | 3 - .../r2dbc/PostgresStatementTest.java | 3 - .../instrumentation/r2dbc/PostgresTest.java | 3 - .../servlet24/HttpServletTest.java | 3 - .../servlet24/HttpSessionTest.java | 3 - .../servlet24/ServletInputStreamTest.java | 3 - .../servlet24/ServletOutputStreamTest.java | 3 - .../servlet24/ServletRequestTest.java | 3 - .../servlet24/ServletResponseTest.java | 3 - .../servlet24/ServletTest.java | 68 --------- .../servlet24/WebServletTest.java | 3 - .../servlet30/ApiEndpointTest.java | 8 +- .../servlet30/HttpServletServer.java | 12 +- .../ServletContainerInitializerTest.java | 8 +- .../instrumentation/servlet5/ServletTest.java | 67 +-------- .../ServletContainerInitializerTest.java | 8 +- .../instrumentation/servlet6/ServletTest.java | 65 +-------- .../httpServer/test/HttpServerTest.java | 104 +++++-------- .../xalan/xpath/XPathTest.java | 3 - .../instrumentator/dispatcher/Dispatcher.java | 9 -- .../newrelic/api/agent/security/Agent.java | 3 +- .../intcodeagent/utils/EncryptorUtils.java | 54 ------- .../newrelic/api/agent/security/Agent.java | 12 +- .../agent/security/schema/AgentMetaData.java | 4 +- .../schema/operation/SQLOperation.java | 13 +- settings.gradle | 2 +- 59 files changed, 153 insertions(+), 1033 deletions(-) delete mode 100644 newrelic-security-api-test-impl/src/main/java/com/newrelic/agent/security/intcodeagent/utils/EncryptorUtils.java diff --git a/Changelog.md b/Changelog.md index 814f0a6b3..1cfb63cde 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,21 +4,6 @@ Noteworthy changes to the agent are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.3.0] - TBD -### Changes -- [NR-222163](https://new-relic.atlassian.net/browse/NR-222163) Feature to detect API Endpoint of the Application [PR-186](https://github.com/newrelic/csec-java-agent/pull/186) -- [NR-171577](https://new-relic.atlassian.net/browse/NR-171577) Resin Support : The security agent now also supports resin server -- [NR-171575](https://new-relic.atlassian.net/browse/NR-171575) Anorm Support : The security agent now also supports Anorm Datastore version 2.0 to 2.5 -- [NR-175383](https://new-relic.atlassian.net/browse/NR-175383) JCache Support : The security agent now also supports jCache 1.0.0 and above [PR-132](https://github.com/newrelic/csec-java-agent/pull/132) -- [NR-230246](https://new-relic.atlassian.net/browse/NR-230246), [NR-230248](https://new-relic.atlassian.net/browse/NR-230248) Spray HTTP Server Support : The security agent now also supports Spray HTTP Server version 1.3.1 and above (with scala 2.11 and above) [PR-193](https://github.com/newrelic/csec-java-agent/pull/193) -- [NR-230246](https://new-relic.atlassian.net/browse/NR-230246), [NR-230248](https://new-relic.atlassian.net/browse/NR-230248) Spray Can Server Support : The security agent now also supports Spray Can Server version 1.3.1 and above (with scala 2.11 and above) [PR-195](https://github.com/newrelic/csec-java-agent/pull/195) -- [NR-230243](https://new-relic.atlassian.net/browse/NR-230243), [NR-230245](https://new-relic.atlassian.net/browse/NR-230245) Spray Client Support : The security agent now also supports Spray Client version 1.3.1 and above (with scala 2.11 and above) [PR-194](https://github.com/newrelic/csec-java-agent/pull/194) -- [NR-234864](https://new-relic.atlassian.net/browse/NR-234864) Netty Server support : The security agent now also supports Netty Server version 4.0.0.Final and above. [PR-202](https://github.com/newrelic/csec-java-agent/pull/202) - -### Fixes -- [NR-238324](https://new-relic.atlassian.net/browse/NR-238324) Extract Server Configuration to resolve IAST localhost connection with application for Netty server. [PR-202](https://github.com/newrelic/csec-java-agent/pull/202) -- Exclude Milestone Release for Jax-RS, due to release of version 4.0.0-M2 on 9th March 2024 [PR-222](https://github.com/newrelic/csec-java-agent/pull/222) - ## [1.2.1] - 2024-4-19 ### Fixes - [NR-259467](https://new-relic.atlassian.net/browse/NR-259467) Fix issue of nested event generation from CSEC's agent itself [PR-230](https://github.com/newrelic/csec-java-agent/pull/230) diff --git a/README.md b/README.md index 38b3a9e37..3da04edb1 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,6 @@ The agent automatically instruments the following frameworks. - Mule ESB 3.6 to 3.9.x - gRPC 1.4.0 to latest** - Jersey 2.0 to latest -- Akka Server 10.0 to latest (with scala 2.11 and above) -- Spray Can 1.3.1 to latest (with scala 2.11 and above) -- Akka HTTP Server 10.0 to latest (with scala 2.11 and above) -- Spray HTTP 1.3.1 to latest (with scala 2.11 and above) -- Netty Server 4.0.0.Final to latest ** IAST for **gRPC** requires the dependency [protobuf-java-util](https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java-util) for IAST request replay. @@ -71,7 +66,6 @@ The agent automatically instruments the following HTTP clients and messaging ser - Xalan XPATH 2.1.0 to latest - Async Http Client from 2.0 to latest - Ning Async HTTP Client 1.0.0 to latest -- Spray Can Client 1.3.1 to latest (with scala 2.11 and above) ### Datastores diff --git a/gradle.properties b/gradle.properties index a5d4ee688..b38b8d652 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # The agent version. -agentVersion=1.3.0 +agentVersion=1.2.2 jsonVersion=1.2.0 # Updated exposed NR APM API version. nrAPIVersion=8.4.0 diff --git a/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala b/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala index be3b24a32..05aaa5904 100644 --- a/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala +++ b/instrumentation-security/akka-http-core-10.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala @@ -15,13 +15,12 @@ import akka.util.ByteString import com.newrelic.agent.security.introspec.{InstrumentationTestConfig, SecurityInstrumentationTestRunner, SecurityIntrospector} import com.newrelic.api.agent.Trace import com.newrelic.api.agent.security.instrumentation.helpers.{GenericHelper, ServletHelper} -import com.newrelic.api.agent.security.schema.{K2RequestIdentifier, SecurityMetaData, StringUtils, VulnerabilityCaseType} +import com.newrelic.api.agent.security.schema.{SecurityMetaData, VulnerabilityCaseType} import com.newrelic.api.agent.security.schema.operation.{RXSSOperation, SSRFOperation} import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.{Assert, FixMethodOrder, Test} -import java.io.File import java.net.ServerSocket import java.util.UUID import scala.collection.JavaConversions @@ -45,13 +44,12 @@ class AkkaHttpCoreTest { val contentType: String = "text/plain" val responseBody: String = "Hoops!" val requestBody: String = "Hurray!" - val fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2" @Test def syncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -69,14 +67,13 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -94,14 +91,13 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def syncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -119,14 +115,13 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -144,7 +139,6 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Trace(dispatcher = true, nameTransaction = true) @@ -189,20 +183,7 @@ class AkkaHttpCoreTest { } port } - private def assertIASTFuzzIdentifier(identifier: K2RequestIdentifier): Unit = { - val f = new File("./tmp123") - val data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false) - Assert.assertTrue(data.length > 4) - Assert.assertNotNull(identifier) - Assert.assertEquals(fuzzHeader, identifier.getRaw) - Assert.assertEquals(data(0), identifier.getApiRecordId) - Assert.assertEquals(data(1), identifier.getRefId) - Assert.assertEquals(data(2), identifier.getRefValue) - Assert.assertEquals(data(3), identifier.getNextStage.getStatus) - Assert.assertEquals(1, identifier.getTempFiles.size) - Assert.assertEquals(f.getPath, identifier.getTempFiles.get(0)) - f.deleteOnExit() - } + private def assertSSRFOperation(operation: SSRFOperation, url: String): Unit = { Assert.assertFalse("operation should not be empty", operation.isEmpty) Assert.assertFalse("JNDILookup should be false", operation.isJNDILookup) diff --git a/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala b/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala index 4e81c7835..727220cd9 100644 --- a/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala +++ b/instrumentation-security/akka-http-core-2.11_10.0.11/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala @@ -15,13 +15,12 @@ import akka.util.ByteString import com.newrelic.agent.security.introspec.{InstrumentationTestConfig, SecurityInstrumentationTestRunner, SecurityIntrospector} import com.newrelic.api.agent.Trace import com.newrelic.api.agent.security.instrumentation.helpers.{GenericHelper, ServletHelper} -import com.newrelic.api.agent.security.schema.{K2RequestIdentifier, SecurityMetaData, StringUtils, VulnerabilityCaseType} +import com.newrelic.api.agent.security.schema.{SecurityMetaData, VulnerabilityCaseType} import com.newrelic.api.agent.security.schema.operation.{RXSSOperation, SSRFOperation} import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.{Assert, FixMethodOrder, Test} -import java.io.File import java.net.ServerSocket import java.util.UUID import scala.collection.JavaConversions @@ -45,13 +44,12 @@ class AkkaHttpCoreTest { val contentType: String = "text/plain" val responseBody: String = "Hoops!" val requestBody: String = "Hurray!" - val fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2" @Test def syncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -69,14 +67,13 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -94,14 +91,13 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def syncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -119,14 +115,13 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -144,7 +139,6 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Trace(dispatcher = true, nameTransaction = true) @@ -205,7 +199,7 @@ class AkkaHttpCoreTest { ) Assert.assertTrue( String.format("Invalid CSEC header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headers.exists(header => header.value().contains(fuzzHeader)) + headers.exists(header => header.value().contains(headerVal)) ) Assert.assertTrue( @@ -226,20 +220,6 @@ class AkkaHttpCoreTest { headers.exists(header => header.value().contains(headerVal)) ) } - private def assertIASTFuzzIdentifier(identifier: K2RequestIdentifier): Unit = { - val f = new File("./tmp123") - val data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false) - Assert.assertTrue(data.length > 4) - Assert.assertNotNull(identifier) - Assert.assertEquals(fuzzHeader, identifier.getRaw) - Assert.assertEquals(data(0), identifier.getApiRecordId) - Assert.assertEquals(data(1), identifier.getRefId) - Assert.assertEquals(data(2), identifier.getRefValue) - Assert.assertEquals(data(3), identifier.getNextStage.getStatus) - Assert.assertEquals(1, identifier.getTempFiles.size) - Assert.assertEquals(f.getPath, identifier.getTempFiles.get(0)) - f.deleteOnExit() - } private def assertRXSSOperation(operation: RXSSOperation): Unit = { Assert.assertFalse("operation should not be empty", operation.isEmpty) Assert.assertFalse("LowSeverityHook should be disabled", operation.isLowSeverityHook) diff --git a/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala b/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala index a92ef0aa8..dd1337dd3 100644 --- a/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala +++ b/instrumentation-security/akka-http-core-2.13_10.2.0/src/test/scala/com/nr/agent/security/instrumentation/akka/http/core_10/AkkaHttpCoreTest.scala @@ -14,13 +14,12 @@ import akka.util.ByteString import com.newrelic.agent.security.introspec.{InstrumentationTestConfig, SecurityInstrumentationTestRunner, SecurityIntrospector} import com.newrelic.api.agent.Trace import com.newrelic.api.agent.security.instrumentation.helpers.{GenericHelper, ServletHelper} -import com.newrelic.api.agent.security.schema.{K2RequestIdentifier, SecurityMetaData, StringUtils, VulnerabilityCaseType} +import com.newrelic.api.agent.security.schema.{SecurityMetaData, VulnerabilityCaseType} import com.newrelic.api.agent.security.schema.operation.{RXSSOperation, SSRFOperation} import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.{Assert, FixMethodOrder, Test} -import java.io.File import java.net.ServerSocket import java.util.UUID import scala.concurrent.duration.DurationInt @@ -43,13 +42,12 @@ class AkkaHttpCoreTest { val contentType: String = "text/plain" val responseBody: String = "Hoops!" val requestBody: String = "Hurray!" - val fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2" @Test def syncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -67,14 +65,13 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithAkkaServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -92,14 +89,13 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def syncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -117,14 +113,13 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Test def asyncHandlerAkkaServerTestWithPlayServer(): Unit = { val headerValue = String.valueOf(UUID.randomUUID) val introspector: SecurityIntrospector = SecurityInstrumentationTestRunner.getIntrospector - introspector.setK2FuzzRequestId(fuzzHeader) + introspector.setK2FuzzRequestId(headerValue) introspector.setK2TracingData(headerValue) introspector.setK2ParentId(headerValue) @@ -142,7 +137,6 @@ class AkkaHttpCoreTest { } } assertMetaData(introspector.getSecurityMetaData) - assertIASTFuzzIdentifier(introspector.getSecurityMetaData.getFuzzRequestIdentifier) } @Trace(dispatcher = true, nameTransaction = true) @@ -187,20 +181,7 @@ class AkkaHttpCoreTest { } port } - private def assertIASTFuzzIdentifier(identifier: K2RequestIdentifier): Unit = { - val f = new File("./tmp123") - val data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false) - Assert.assertTrue(data.length > 4) - Assert.assertNotNull(identifier) - Assert.assertEquals(fuzzHeader, identifier.getRaw) - Assert.assertEquals(data(0), identifier.getApiRecordId) - Assert.assertEquals(data(1), identifier.getRefId) - Assert.assertEquals(data(2), identifier.getRefValue) - Assert.assertEquals(data(3), identifier.getNextStage.getStatus) - Assert.assertEquals(1, identifier.getTempFiles.size) - Assert.assertEquals(f.getPath, identifier.getTempFiles.get(0)) - f.deleteOnExit() - } + private def assertSSRFOperation(operation: SSRFOperation, url: String): Unit = { Assert.assertFalse("operation should not be empty", operation.isEmpty) Assert.assertFalse("JNDILookup should be false", operation.isJNDILookup) diff --git a/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java index e27acd60a..73c5b14d6 100644 --- a/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java +++ b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java @@ -32,6 +32,9 @@ public class APIEndpointTest { public void setupEndpoints() { expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); expectedMappings.put("/index.jsp", null); + expectedMappings.put("/*.jsp", "org.apache.jasper.servlet.JspServlet"); + expectedMappings.put("/", DefaultServlet.class.getName()); + expectedMappings.put("/*.jspx", "org.apache.jasper.servlet.JspServlet"); } @Test @@ -40,7 +43,7 @@ public void testAPIEndpoint() throws Exception { Set mappings = URLMappingsHelper.getApplicationURLMappings(); Assert.assertNotNull(mappings); - Assert.assertEquals(2, mappings.size()); + Assert.assertEquals(5, mappings.size()); for (ApplicationURLMapping mapping : mappings) { assertMappings(mapping); } diff --git a/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java index 338994b59..e382baadf 100644 --- a/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java +++ b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java @@ -32,6 +32,9 @@ public class APIEndpointTest { public void setupEndpoints() { expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); expectedMappings.put("/index.jsp", null); + expectedMappings.put("/*.jsp", "org.apache.jasper.servlet.JspServlet"); + expectedMappings.put("/", DefaultServlet.class.getName()); + expectedMappings.put("/*.jspx", "org.apache.jasper.servlet.JspServlet"); } @Test @@ -40,7 +43,7 @@ public void testAPIEndpoint() throws Exception { Set mappings = URLMappingsHelper.getApplicationURLMappings(); Assert.assertNotNull(mappings); - Assert.assertEquals(2, mappings.size()); + Assert.assertEquals(5, mappings.size()); for (ApplicationURLMapping mapping : mappings) { assertMappings(mapping); } diff --git a/instrumentation-security/grpc-1.22.0/src/test/java/com/nr/agent/security/instrumentation/grpc1220/GrpcTest.java b/instrumentation-security/grpc-1.22.0/src/test/java/com/nr/agent/security/instrumentation/grpc1220/GrpcTest.java index 346d85c11..98b4cf6a3 100644 --- a/instrumentation-security/grpc-1.22.0/src/test/java/com/nr/agent/security/instrumentation/grpc1220/GrpcTest.java +++ b/instrumentation-security/grpc-1.22.0/src/test/java/com/nr/agent/security/instrumentation/grpc1220/GrpcTest.java @@ -11,11 +11,8 @@ import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; -import com.newrelic.api.agent.security.schema.K2RequestIdentifier; -import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; @@ -27,7 +24,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import java.io.File; import java.util.List; import java.util.UUID; @@ -39,7 +35,6 @@ public class GrpcTest { private static TestServer server; private static TestClient client; - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @BeforeClass public static void before() throws Exception { @@ -63,9 +58,8 @@ public void testBlockingRequest() throws JsonProcessingException { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); - introspector.setK2ParentId(headerValue); client.helloBlocking("Blocking"); @@ -96,18 +90,14 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Blocking\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Blocking\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -115,9 +105,8 @@ public void testFutureRequest() throws Exception { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); - introspector.setK2ParentId(headerValue); client.helloFuture("Future"); @@ -148,18 +137,14 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Future\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Future\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -167,9 +152,8 @@ public void testAsyncRequest() throws JsonProcessingException, InterruptedExcept String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); - introspector.setK2ParentId(headerValue); client.helloAsync("Async"); // wait for async call to finish @@ -202,18 +186,14 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Async\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Async\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -221,9 +201,8 @@ public void testStreamingRequest() throws JsonProcessingException, InterruptedEx String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); - introspector.setK2ParentId(headerValue); client.helloStreaming("Streaming"); // wait for streaming to finish @@ -256,31 +235,13 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Streaming1\"},{\"name\":\"Streaming2\"},{\"name\":\"Streaming3\"},{\"name\":\"Streaming4\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Streaming1\"},{\"message\":\"Hello Streaming2\"},{\"message\":\"Hello Streaming3\"},{\"message\":\"Hello Streaming4\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); - } - private void assertCSECHeaders(K2RequestIdentifier identifier){ - File f = new File("./tmp123"); - String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); - Assert.assertTrue(data.length > 4); - Assert.assertNotNull(identifier); - Assert.assertEquals(fuzzHeader, identifier.getRaw()); - Assert.assertEquals(data[0], identifier.getApiRecordId()); - Assert.assertEquals(data[1], identifier.getRefId()); - Assert.assertEquals(data[2], identifier.getRefValue()); - Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); - Assert.assertEquals(1, identifier.getTempFiles().size()); - Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); - f.deleteOnExit(); } } diff --git a/instrumentation-security/grpc-1.4.0/src/test/java/com/nr/agent/security/instrumentation/grpc140/GrpcTest.java b/instrumentation-security/grpc-1.4.0/src/test/java/com/nr/agent/security/instrumentation/grpc140/GrpcTest.java index 775e5bc1e..afb94e295 100644 --- a/instrumentation-security/grpc-1.4.0/src/test/java/com/nr/agent/security/instrumentation/grpc140/GrpcTest.java +++ b/instrumentation-security/grpc-1.4.0/src/test/java/com/nr/agent/security/instrumentation/grpc140/GrpcTest.java @@ -8,9 +8,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; -import com.newrelic.api.agent.security.schema.K2RequestIdentifier; -import com.newrelic.api.agent.security.schema.StringUtils; import com.nr.agent.security.instrumentation.grpc140.app.TestServer; import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; @@ -27,7 +24,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import java.io.File; import java.util.List; import java.util.UUID; @@ -39,7 +35,6 @@ public class GrpcTest { private static TestServer server; private static TestClient client; - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @BeforeClass public static void before() throws Exception { @@ -63,9 +58,8 @@ public void testBlockingRequest() throws JsonProcessingException { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); - introspector.setK2ParentId(headerValue); client.helloBlocking("Blocking"); @@ -96,18 +90,14 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Blocking\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Blocking\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -115,9 +105,8 @@ public void testFutureRequest() throws Exception { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); - introspector.setK2ParentId(headerValue); client.helloFuture("Future"); @@ -148,18 +137,14 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Future\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Future\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -167,8 +152,7 @@ public void testAsyncRequest() throws JsonProcessingException, InterruptedExcept String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); - introspector.setK2ParentId(headerValue); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); client.helloAsync("Async"); @@ -202,18 +186,14 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Async\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Async\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -221,8 +201,7 @@ public void testStreamingRequest() throws JsonProcessingException, InterruptedEx String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); - introspector.setK2ParentId(headerValue); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); client.helloStreaming("Streaming"); @@ -256,31 +235,13 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Streaming1\"},{\"name\":\"Streaming2\"},{\"name\":\"Streaming3\"},{\"name\":\"Streaming4\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Streaming1\"},{\"message\":\"Hello Streaming2\"},{\"message\":\"Hello Streaming3\"},{\"message\":\"Hello Streaming4\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); - } - private void assertCSECHeaders(K2RequestIdentifier identifier){ - File f = new File("./tmp123"); - String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); - Assert.assertTrue(data.length > 4); - Assert.assertNotNull(identifier); - Assert.assertEquals(fuzzHeader, identifier.getRaw()); - Assert.assertEquals(data[0], identifier.getApiRecordId()); - Assert.assertEquals(data[1], identifier.getRefId()); - Assert.assertEquals(data[2], identifier.getRefValue()); - Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); - Assert.assertEquals(1, identifier.getTempFiles().size()); - Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); - f.deleteOnExit(); } } diff --git a/instrumentation-security/grpc-1.40.0/src/test/java/com/nr/agent/security/instrumentation/grpc1400/GrpcTest.java b/instrumentation-security/grpc-1.40.0/src/test/java/com/nr/agent/security/instrumentation/grpc1400/GrpcTest.java index 5b1d57174..bfe97effa 100644 --- a/instrumentation-security/grpc-1.40.0/src/test/java/com/nr/agent/security/instrumentation/grpc1400/GrpcTest.java +++ b/instrumentation-security/grpc-1.40.0/src/test/java/com/nr/agent/security/instrumentation/grpc1400/GrpcTest.java @@ -11,11 +11,8 @@ import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; -import com.newrelic.api.agent.security.schema.K2RequestIdentifier; -import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; @@ -27,7 +24,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import java.io.File; import java.util.List; import java.util.UUID; @@ -39,7 +35,6 @@ public class GrpcTest { private static TestServer server; private static TestClient client; - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @BeforeClass public static void before() throws Exception { @@ -63,9 +58,8 @@ public void testBlockingRequest() throws JsonProcessingException { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); - introspector.setK2ParentId(headerValue); client.helloBlocking("Blocking"); @@ -95,18 +89,15 @@ else if (op instanceof RXSSOperation) { Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Blocking\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Blocking\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -114,9 +105,8 @@ public void testFutureRequest() throws Exception { String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); - introspector.setK2ParentId(headerValue); client.helloFuture("Future"); @@ -147,18 +137,14 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Future\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Future\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -166,9 +152,8 @@ public void testAsyncRequest() throws JsonProcessingException, InterruptedExcept String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); - introspector.setK2ParentId(headerValue); client.helloAsync("Async"); // wait for async call to finish @@ -201,18 +186,14 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Async\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Async\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } @Test @@ -220,9 +201,8 @@ public void testStreamingRequest() throws JsonProcessingException, InterruptedEx String headerValue = String.valueOf(UUID.randomUUID()); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - introspector.setK2FuzzRequestId(fuzzHeader); + introspector.setK2FuzzRequestId(headerValue); introspector.setK2TracingData(headerValue); - introspector.setK2ParentId(headerValue); client.helloStreaming("Streaming"); // wait for streaming to finish @@ -255,31 +235,13 @@ else if (op instanceof RXSSOperation) { Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue+";DUMMY_UUID/dummy-api-id/dummy-exec-id", operation.getRequest().getHeaders().get( ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), operation.getRequest().getHeaders().containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, operation.getRequest().getHeaders().get( + Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headerValue, operation.getRequest().getHeaders().get( ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), operation.getRequest().getHeaders().containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, operation.getRequest().getHeaders().get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); } } String request = new ObjectMapper().writeValueAsString(introspector.getGRPCRequest()); String response = new ObjectMapper().writeValueAsString(introspector.getGRPCResponse()); Assert.assertEquals("Invalid request body.", "[{\"name\":\"Streaming1\"},{\"name\":\"Streaming2\"},{\"name\":\"Streaming3\"},{\"name\":\"Streaming4\"}]", request); Assert.assertEquals("Invalid response body.", "[{\"message\":\"Hello Streaming1\"},{\"message\":\"Hello Streaming2\"},{\"message\":\"Hello Streaming3\"},{\"message\":\"Hello Streaming4\"}]", response); - assertCSECHeaders(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); - } - private void assertCSECHeaders(K2RequestIdentifier identifier){ - File f = new File("./tmp123"); - String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); - Assert.assertTrue(data.length > 4); - Assert.assertNotNull(identifier); - Assert.assertEquals(fuzzHeader, identifier.getRaw()); - Assert.assertEquals(data[0], identifier.getApiRecordId()); - Assert.assertEquals(data[1], identifier.getRefId()); - Assert.assertEquals(data[2], identifier.getRefValue()); - Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); - Assert.assertEquals(1, identifier.getTempFiles().size()); - Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); - f.deleteOnExit(); } } diff --git a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java index ae2c1e942..6f0e71eae 100644 --- a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java +++ b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextRmiTest.java @@ -7,11 +7,9 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; import com.newrelic.agent.security.instrumentation.javax.jndi.JNDIUtils; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -32,7 +30,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.naming", "com.newrelic.agent.security.instrumentation.javax.jndi" } ) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Category({ Java17IncompatibleTest.class}) public class ContextRmiTest { private final int PORT = getRandomPort(); diff --git a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java index fd5118c93..b4295dc77 100644 --- a/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java +++ b/instrumentation-security/javax-jndi/src/test/java/com/nr/agent/security/instrumentation/javax/jndi/ContextTest.java @@ -7,14 +7,12 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; import com.newrelic.agent.security.instrumentation.javax.jndi.JNDIUtils; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import com.unboundid.ldap.sdk.LDAPException; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.zapodot.junit.ldap.EmbeddedLdapRule; @@ -32,7 +30,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.naming", "com.newrelic.agent.security.instrumentation.javax.jndi" } ) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Category({ Java17IncompatibleTest.class}) public class ContextTest { public static final String DOMAIN_DSN = "dc=example,dc=com"; @ClassRule diff --git a/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java b/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java index aa134a824..4d50e493c 100644 --- a/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java +++ b/instrumentation-security/javax-ldap/src/test/java/com/nr/agent/security/instrumentation/javax/ldap/DirContextTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.LDAPOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.LDAPInterface; import org.junit.Assert; @@ -15,7 +14,6 @@ import org.junit.FixMethodOrder; import org.junit.Ignore; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.zapodot.junit.ldap.EmbeddedLdapRule; @@ -37,7 +35,6 @@ @FixMethodOrder(MethodSorters.NAME_ASCENDING) //FIXME: after instrumentation works @Ignore -@Category({ Java17IncompatibleTest.class}) public class DirContextTest { public static final String DOMAIN_DSN = "dc=example,dc=com"; @ClassRule diff --git a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java index f4eabe154..d73b39901 100644 --- a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java +++ b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/JavaxWsRsApiTest.java @@ -4,16 +4,13 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.security.schema.AgentMetaData; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.App; import org.junit.Assert; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "com.newrelic.agent.security.instrumentation.javax.ws.rs.api") -@Category({ Java17IncompatibleTest.class}) public class JavaxWsRsApiTest { @Test public void testPut() { diff --git a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java index 33d5e9986..a67197b37 100644 --- a/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java +++ b/instrumentation-security/jax-rs-1.0/src/test/java/com/nr/agent/security/instrumentation/javax/ws/rs/api/test/SubresourceTest.java @@ -1,6 +1,5 @@ package com.nr.agent.security.instrumentation.javax.ws.rs.api.test; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.CustomerLocatorResource; import com.nr.agent.security.instrumentation.javax.ws.rs.api.app.IdSubResource; import com.newrelic.agent.security.introspec.InstrumentationTestConfig; @@ -14,7 +13,6 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import javax.ws.rs.client.Entity; @@ -23,7 +21,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "com.newrelic.agent.security.instrumentation.javax.ws.rs.api") -@Category({ Java17IncompatibleTest.class}) public class SubresourceTest extends JerseyTest { @BeforeClass public static void bringUp() { diff --git a/instrumentation-security/jaxen-xpath-1.1/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java b/instrumentation-security/jaxen-xpath-1.1/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java index 21e3a1a5b..9e3579340 100644 --- a/instrumentation-security/jaxen-xpath-1.1/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java +++ b/instrumentation-security/jaxen-xpath-1.1/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.XPathOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.jaxen.BaseXPath; import org.jaxen.Context; import org.jaxen.ContextSupport; @@ -19,7 +18,6 @@ import org.jaxen.xom.XOMXPath; import org.junit.Assert; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.w3c.dom.Document; @@ -28,7 +26,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "com.newrelic.agent.security.instrumentation.xpath.jaxen", "org.jaxen" }) -@Category({ Java17IncompatibleTest.class}) public class BaseXPathTest { private final String EXPRESSION = "/Customers/Customer"; private final String XML_DOC = "src/test/resources/Customer.xml"; diff --git a/instrumentation-security/jaxen-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java b/instrumentation-security/jaxen-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java index 01a62ce9e..a370cb9d2 100644 --- a/instrumentation-security/jaxen-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java +++ b/instrumentation-security/jaxen-xpath/src/test/java/com/nr/agent/security/instrumentation/xpath/jaxen/BaseXPathTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.XPathOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.jaxen.BaseXPath; import org.jaxen.Context; import org.jaxen.ContextSupport; @@ -19,7 +18,6 @@ import org.jaxen.xom.XOMXPath; import org.junit.Assert; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.w3c.dom.Document; @@ -29,7 +27,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "com.newrelic.instrumentation.security.xpath.jaxen", "org.jaxen" }) -@Category({ Java17IncompatibleTest.class}) public class BaseXPathTest { private final String EXPRESSION = "/Customers/Customer"; private final String XML_DOC = "src/test/resources/Customer.xml"; diff --git a/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java b/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java index b78888973..0690ce8f6 100644 --- a/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java +++ b/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java @@ -22,8 +22,6 @@ import com.newrelic.api.agent.weaver.Weaver; import java.math.BigDecimal; -import java.net.URL; -import java.util.Calendar; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; @@ -34,9 +32,6 @@ public abstract class PreparedStatement_Instrumentation { @NewField private Map params; - - @NewField - private Map objectParams; @NewField String preparedSql; @NewField @@ -241,128 +236,6 @@ public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { Weaver.callOriginal(); } - public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { - setParamValue(parameterIndex, xmlObject.getString()); - Weaver.callOriginal(); - } - - public void setRowId(int parameterIndex, RowId x) throws SQLException { - setParamValue(parameterIndex, x.toString()); - Weaver.callOriginal(); - } - - public void setURL(int parameterIndex, java.net.URL x) throws SQLException { - setParamValue(parameterIndex, x.toString()); - Weaver.callOriginal(); - } - - public void setArray (int parameterIndex, Array x) throws SQLException { - setObjectParams(parameterIndex, x.getArray()); - Weaver.callOriginal(); - } - public void setDate(int parameterIndex, java.sql.Date x, Calendar cal) throws SQLException { - setParamValue(parameterIndex, x); - Weaver.callOriginal(); - } - public void setTime(int parameterIndex, java.sql.Time x, Calendar cal) throws SQLException { - setParamValue(parameterIndex, x); - Weaver.callOriginal(); - } - public void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal) throws SQLException { - setParamValue(parameterIndex, x); - Weaver.callOriginal(); - } - public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { - setParamValue(parameterIndex, "null"); - Weaver.callOriginal(); - } - public void setNString(int parameterIndex, String value) throws SQLException { - setParamValue(parameterIndex, value); - Weaver.callOriginal(); - } - - public void setObject(int parameterIndex, Object x) throws SQLException { - if(x instanceof Long || x instanceof Integer || x instanceof Double || - x instanceof Float || x instanceof Boolean || x instanceof Short || - x instanceof String || x instanceof byte[] || x instanceof Timestamp || - x instanceof Date || x instanceof BigDecimal || x instanceof Time) { - setParamValue(parameterIndex, x); - } else if (x instanceof SQLXML) { - setParamValue(parameterIndex, ((SQLXML) x).getString()); - } else if (x instanceof RowId || x instanceof URL) { - setParamValue(parameterIndex, x.toString()); - } else { - //TODO critical-message for inconvertible - setObjectParams(parameterIndex, x); - } - Weaver.callOriginal(); - } - - public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { - if(x instanceof Long || x instanceof Integer || x instanceof Double || - x instanceof Float || x instanceof Boolean || x instanceof Short || - x instanceof String || x instanceof byte[] || x instanceof Timestamp || - x instanceof Date || x instanceof BigDecimal || x instanceof Time) { - setParamValue(parameterIndex, x); - } else if (x instanceof SQLXML) { - setParamValue(parameterIndex, ((SQLXML) x).getString()); - } else if (x instanceof RowId || x instanceof URL) { - setParamValue(parameterIndex, x.toString()); - } else { - NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); - setObjectParams(parameterIndex, x); - } - Weaver.callOriginal(); - } - public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { - if(x instanceof Long || x instanceof Integer || x instanceof Double || - x instanceof Float || x instanceof Boolean || x instanceof Short || - x instanceof String || x instanceof byte[] || x instanceof Timestamp || - x instanceof Date || x instanceof BigDecimal || x instanceof Time) { - setParamValue(parameterIndex, x); - } else if (x instanceof SQLXML) { - setParamValue(parameterIndex, ((SQLXML) x).getString()); - } else if (x instanceof RowId || x instanceof URL) { - setParamValue(parameterIndex, x.toString()); - } else { - NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); - setObjectParams(parameterIndex, x); - } - Weaver.callOriginal(); - } - public void setObject(int parameterIndex, Object x, SQLType targetSqlType) throws SQLException { - if(x instanceof Long || x instanceof Integer || x instanceof Double || - x instanceof Float || x instanceof Boolean || x instanceof Short || - x instanceof String || x instanceof byte[] || x instanceof Timestamp || - x instanceof Date || x instanceof BigDecimal || x instanceof Time) { - setParamValue(parameterIndex, x); - } else if (x instanceof SQLXML) { - setParamValue(parameterIndex, ((SQLXML) x).getString()); - } else if (x instanceof RowId || x instanceof URL) { - setParamValue(parameterIndex, x.toString()); - } else { - NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); - setObjectParams(parameterIndex, x); - } - Weaver.callOriginal(); - } - public void setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { - if(x instanceof Long || x instanceof Integer || x instanceof Double || - x instanceof Float || x instanceof Boolean || x instanceof Short || - x instanceof String || x instanceof byte[] || x instanceof Timestamp || - x instanceof Date || x instanceof BigDecimal || x instanceof Time) { - setParamValue(parameterIndex, x); - } else if (x instanceof SQLXML) { - setParamValue(parameterIndex, ((SQLXML) x).getString()); - } else if (x instanceof RowId || x instanceof URL) { - setParamValue(parameterIndex, x.toString()); - } else { - NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); - setObjectParams(parameterIndex, x); - } - Weaver.callOriginal(); - } - public void clearParameters() throws SQLException { if(params != null){ params.clear(); @@ -387,13 +260,6 @@ private void setParamValue(int index, byte[] value) { params.put(String.valueOf(index), new String(value)); } - private void setObjectParams(int index, Object data) { - if (objectParams == null) { - objectParams = new HashMap<>(); - } - - objectParams.put(String.valueOf(index), data); - } public void addBatch() throws SQLException { boolean isLockAcquired = acquireLockIfPossible(); SQLOperation sqlOperation = null; @@ -403,9 +269,6 @@ public void addBatch() throws SQLException { Map localParams = new HashMap<>(); localParams.putAll(params); sqlOperation.setParams(localParams); - Map localObjParams = new HashMap<>(); - localObjParams.putAll(objectParams); - sqlOperation.setObjectParams(localObjParams); sqlOperation.setDbName(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(JDBCVendor.META_CONST_JDBC_VENDOR, String.class)); sqlOperation.setPreparedCall(true); if(batchSQLOperation==null) diff --git a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DataStoreTest.java b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DataStoreTest.java index 53d4c81df..413309216 100644 --- a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DataStoreTest.java +++ b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DataStoreTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -38,7 +37,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DriverTest.java b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DriverTest.java index 51158d48c..52a165ea4 100644 --- a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DriverTest.java +++ b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/DriverTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -30,7 +29,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/PgStatementTest.java b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/PgStatementTest.java index 44e39e502..63c84079e 100644 --- a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/PgStatementTest.java +++ b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/test/java/com/nr/agent/security/instrumentation/postgresql80312/PgStatementTest.java @@ -8,7 +8,6 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SQLOperation; import com.newrelic.security.test.marker.Java12IncompatibleTest; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -38,7 +37,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DataStoreTest.java b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DataStoreTest.java index f597ecb4d..f99de0c46 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DataStoreTest.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DataStoreTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -39,7 +38,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DriverTest.java b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DriverTest.java index 9c6e675d7..92a741464 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DriverTest.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/DriverTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -30,7 +29,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/PgStatementTest.java b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/PgStatementTest.java index 52865421c..48b935998 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/PgStatementTest.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1207/src/test/java/com/nr/agent/security/instrumentation/postgresql941207/PgStatementTest.java @@ -8,7 +8,6 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SQLOperation; import com.newrelic.security.test.marker.Java12IncompatibleTest; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -38,7 +37,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DataStoreTest.java b/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DataStoreTest.java index 89ac790ed..336e52ad7 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DataStoreTest.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DataStoreTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -39,7 +38,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DriverTest.java b/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DriverTest.java index bb8bfe5ac..1dc172a07 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DriverTest.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1208/src/test/java/com/nr/agent/security/instrumentation/postgresql941208/DriverTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.JDBCVendor; import com.newrelic.security.test.marker.Java12IncompatibleTest; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -31,7 +30,7 @@ import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; import static ru.yandex.qatools.embed.postgresql.distribution.Version.V11_1; -@Category({ Java12IncompatibleTest.class, Java17IncompatibleTest.class }) +@Category({ Java12IncompatibleTest.class }) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "org.postgresql") @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java b/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java index 472b63421..d3ccc680e 100644 --- a/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java +++ b/instrumentation-security/jersey-2.16/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java @@ -59,7 +59,7 @@ @InstrumentationTestConfig(includePrefixes = {"com.newrelic.agent.security.instrumentation.jersey2", "org.glassfish.jersey"}) @Category({ Java9IncompatibleTest.class, Java11IncompatibleTest.class, Java17IncompatibleTest.class }) public class JerseyTests { - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; + private static HttpServer server; private static int port; private static final String PACKAGE = "com.nr.agent.security.instrumentation.jersey2.resources"; @@ -136,7 +136,7 @@ private String[] fireRequest1(final String path) { Client client = ClientBuilder.newClient(); WebTarget target = client.target(url.toString()).path(path); try ( Response response = target.request().header(Header.ContentType.toString(), MediaType.APPLICATION_JSON) - .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader) + .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue) .header(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue) .header(GenericHelper.CSEC_PARENT_ID, headerValue) .get(); @@ -177,7 +177,7 @@ private void assertOperation(List operations, boolean hasHead ); assertEquals( String.format("Invalid CSEC header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - fuzzHeader, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + headerValue, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); assertTrue( String.format("Missing CSEC header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), diff --git a/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java b/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java index 506842f14..f418c45e8 100644 --- a/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java +++ b/instrumentation-security/jersey-2/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java @@ -65,7 +65,6 @@ public class JerseyTests { private static final String PACKAGE = "com.nr.agent.security.instrumentation.jersey2.resources"; private static URL url; private final String headerValue = String.valueOf(UUID.randomUUID()); - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @BeforeClass public static void setUp() throws MalformedURLException, URISyntaxException { @@ -139,7 +138,7 @@ private String[] fireRequest1(final String path) { Client client = ClientBuilder.newClient(); WebTarget target = client.target(url.toString()).path(path); Response response = target.request().header(Header.ContentType.toString(), MediaType.APPLICATION_JSON) - .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader) + .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue) .header(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue) .header(GenericHelper.CSEC_PARENT_ID, headerValue) .get(); @@ -181,7 +180,7 @@ private void assertOperation(List operations, boolean hasHead ); assertEquals( String.format("Invalid CSEC header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - fuzzHeader, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + headerValue, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); assertTrue( String.format("Missing CSEC header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), diff --git a/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java b/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java index 4b67f8644..85ec2d538 100644 --- a/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java +++ b/instrumentation-security/jersey-3/src/test/java/com/nr/agent/security/instrumentation/jersey2/JerseyTests.java @@ -58,7 +58,7 @@ @InstrumentationTestConfig(includePrefixes = {"com.newrelic.agent.security.instrumentation.jersey2", "org.glassfish.jersey"}) @Category({Java8IncompatibleTest.class, Java11IncompatibleTest.class}) public class JerseyTests { - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; + private static HttpServer server; private static int port; private static final String PACKAGE = "com.nr.agent.security.instrumentation.jersey2.resources"; @@ -135,7 +135,7 @@ private String[] fireRequest1(final String path) { Client client = ClientBuilder.newClient(); WebTarget target = client.target(url.toString()).path(path); try ( Response response = target.request().header(Header.ContentType.toString(), MediaType.APPLICATION_JSON) - .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader) + .header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue) .header(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue) .header(GenericHelper.CSEC_PARENT_ID, headerValue) .get(); @@ -177,7 +177,7 @@ private void assertOperation(List operations, boolean hasHead ); assertEquals( String.format("Invalid CSEC header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - fuzzHeader, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + headerValue, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); assertTrue( String.format("Missing CSEC header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), diff --git a/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java b/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java index 09cd81957..78269c9d6 100644 --- a/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java +++ b/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java @@ -4,14 +4,11 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; -import com.newrelic.api.agent.security.schema.K2RequestIdentifier; -import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.agent.security.instrumentation.jetty11.HttpServletHelper; @@ -19,9 +16,11 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.junit.After; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; @@ -30,12 +29,11 @@ import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - -import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.ServerSocket; import java.net.URL; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -49,6 +47,13 @@ public class ServerTest { public final static String ENDPOINT = String.format("http://localhost:%d/", PORT); private Server server; + + private static final Map actualMappings = new HashMap<>(); + @BeforeClass + public static void addMappings() { + actualMappings.put("/servlet/*", MyServlet.class.getName()); + actualMappings.put("/", ServletHandler.Default404Servlet.class.getName()); + } @After public void teardown() throws Exception { if (server.isRunning()) { @@ -196,96 +201,18 @@ public void testAPIEndpoint () throws Exception { start(); Set mappings = URLMappingsHelper.getApplicationURLMappings(); - Assert.assertEquals(1, mappings.size()); + Assert.assertEquals(2, mappings.size()); for (ApplicationURLMapping mapping : mappings) { Assert.assertNotNull(mapping); Assert.assertNotNull(mapping.getHandler()); Assert.assertNotNull(mapping.getPath()); Assert.assertNotNull(mapping.getMethod()); - Assert.assertEquals("/servlet/*", mapping.getPath());; - Assert.assertEquals(MyServlet.class.getName(), mapping.getHandler()); + + Assert.assertEquals(actualMappings.get(mapping.getPath()), mapping.getHandler()); Assert.assertEquals("*", mapping.getMethod()); } } - @Test - public void testCSECHeaders() throws Exception { - start(); - String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; - String headerValue = serviceWithHeaders(fuzzHeader); - - Thread.sleep(100); - SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - List operations = introspector.getOperations(); - Assert.assertFalse("No operations detected", operations.isEmpty()); - Assert.assertEquals("Extra operations detected", 1, operations.size()); - - RXSSOperation targetOperation = (RXSSOperation) operations.get(0); - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); - Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); - Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); - - Assert.assertEquals("Wrong port detected", PORT, targetOperation.getRequest().getServerPort()); - Assert.assertEquals("Wrong method name detected", "handle", targetOperation.getMethodName()); - Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - - Map headers = targetOperation.getRequest().getHeaders(); - Assert.assertTrue( - String.format("Missing header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) - ); - Assert.assertEquals( - String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - fuzzHeader, - headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) - ); - Assert.assertTrue( - String.format("Missing header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), - headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) - ); - Assert.assertEquals( - String.format("Invalid header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), - headerValue, - headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) - ); - Assert.assertTrue( - String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), - headers.containsKey(GenericHelper.CSEC_PARENT_ID) - ); - Assert.assertEquals( - String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), - headerValue, headers.get(GenericHelper.CSEC_PARENT_ID) - ); - - File f = new File("./tmp123"); - K2RequestIdentifier identifier = introspector.getSecurityMetaData().getFuzzRequestIdentifier(); - String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); - Assert.assertTrue(data.length > 4); - Assert.assertNotNull(identifier); - Assert.assertEquals(fuzzHeader, identifier.getRaw()); - Assert.assertEquals(data[0], identifier.getApiRecordId()); - Assert.assertEquals(data[1], identifier.getRefId()); - Assert.assertEquals(data[2], identifier.getRefValue()); - Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); - Assert.assertEquals(1, identifier.getTempFiles().size()); - Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); - f.deleteOnExit(); - } - @Trace(dispatcher = true) - private String serviceWithHeaders(String fuzzHeader) throws IOException { - String headerValue = String.valueOf(UUID.randomUUID()); - URL url = new URL(ENDPOINT); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); - - conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); - conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); - conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); - conn.connect(); - conn.getResponseCode(); - return headerValue; - } private void start() throws Exception { server = new Server(PORT); ServletHolder holder = new ServletHolder(new MyServlet()); diff --git a/instrumentation-security/jetty-12/src/test/java/com/nr/agent/security/instrumentation/jetty12/test/ServerTest.java b/instrumentation-security/jetty-12/src/test/java/com/nr/agent/security/instrumentation/jetty12/test/ServerTest.java index b4cac74de..71bcdb51c 100644 --- a/instrumentation-security/jetty-12/src/test/java/com/nr/agent/security/instrumentation/jetty12/test/ServerTest.java +++ b/instrumentation-security/jetty-12/src/test/java/com/nr/agent/security/instrumentation/jetty12/test/ServerTest.java @@ -4,7 +4,6 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -42,7 +41,7 @@ public class ServerTest { public static int PORT = 0; public static String ENDPOINT = "http://localhost:%d/"; - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; + private Server server; @After @@ -84,7 +83,7 @@ public void testHandle() throws Exception { ); Assert.assertEquals( String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - fuzzHeader, + headerValue, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); Assert.assertTrue( @@ -96,15 +95,6 @@ public void testHandle() throws Exception { headerValue, headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) ); - Assert.assertTrue( - String.format("Missing header: %s", GenericHelper.CSEC_PARENT_ID), - headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase()) - ); - Assert.assertEquals( - String.format("Invalid header value for: %s", GenericHelper.CSEC_PARENT_ID), - headerValue, - headers.get(GenericHelper.CSEC_PARENT_ID.toLowerCase()) - ); } @Test @@ -137,7 +127,7 @@ public void testHandle1() throws Exception { ); Assert.assertEquals( String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - fuzzHeader, + headerValue, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); Assert.assertTrue( @@ -149,15 +139,6 @@ public void testHandle1() throws Exception { headerValue, headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) ); - Assert.assertTrue( - String.format("Missing header: %s", GenericHelper.CSEC_PARENT_ID), - headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase()) - ); - Assert.assertEquals( - String.format("Invalid header value for: %s", GenericHelper.CSEC_PARENT_ID), - headerValue, - headers.get(GenericHelper.CSEC_PARENT_ID.toLowerCase()) - ); } @Test @@ -266,7 +247,7 @@ public void testHandle5() throws Exception { ); Assert.assertEquals( String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - fuzzHeader, + headerValue, headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) ); Assert.assertTrue( @@ -278,15 +259,6 @@ public void testHandle5() throws Exception { headerValue, headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) ); - Assert.assertTrue( - String.format("Missing header: %s", GenericHelper.CSEC_PARENT_ID), - headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase()) - ); - Assert.assertEquals( - String.format("Invalid header value for: %s", GenericHelper.CSEC_PARENT_ID), - headerValue, - headers.get(GenericHelper.CSEC_PARENT_ID.toLowerCase()) - ); } private void startWithServlet() throws Exception { @@ -348,9 +320,8 @@ private String serviceWithHeaders() throws Exception { conn.setRequestProperty("content-type", "text/plain;charset=utf-8"); conn.setRequestMethod("GET"); - conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue); conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); - conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); conn.connect(); conn.getResponseCode(); diff --git a/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java b/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java index 5e05a60c2..e7f236937 100644 --- a/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java +++ b/instrumentation-security/jetty-9/src/test/java/com/nr/agent/security/instrumentation/jetty9/ServerTest.java @@ -4,18 +4,14 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; -import com.newrelic.api.agent.security.schema.K2RequestIdentifier; -import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.agent.security.instrumentation.jetty9.HttpServletHelper; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; @@ -25,18 +21,15 @@ import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.ServerSocket; -import java.net.URISyntaxException; import java.net.URL; import java.util.List; import java.util.Map; @@ -46,7 +39,6 @@ @FixMethodOrder(MethodSorters.NAME_ASCENDING) @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = {"org.eclipse.jetty", "com.newrelic.agent.security.instrumentation.jetty9"}) -@Category({ Java17IncompatibleTest.class}) public class ServerTest { public final static int PORT = getRandomPort(); public final static String ENDPOINT = String.format("http://localhost:%d/", PORT); @@ -194,84 +186,6 @@ public void testHandle3() throws Exception { Assert.assertEquals("Wrong port detected", PORT, operation.getRequest().getServerPort()); Assert.assertEquals("Wrong Content-type detected", "text/plain", operation.getRequest().getContentType()); } - @Test - public void testCSECHeaders() throws Exception { - start1(); - String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; - String headerValue = serviceWithHeaders(fuzzHeader); - - Thread.sleep(100); - SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - List operations = introspector.getOperations(); - Assert.assertFalse("No operations detected", operations.isEmpty()); - Assert.assertEquals("Extra operations detected", 1, operations.size()); - - RXSSOperation targetOperation = (RXSSOperation) operations.get(0); - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); - Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); - Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); - - Assert.assertEquals("Wrong port detected", PORT, targetOperation.getRequest().getServerPort()); - Assert.assertEquals("Wrong method name detected", "handle", targetOperation.getMethodName()); - Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - - Map headers = targetOperation.getRequest().getHeaders(); - Assert.assertTrue( - String.format("Missing header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) - ); - Assert.assertEquals( - String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), - fuzzHeader, - headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) - ); - Assert.assertTrue( - String.format("Missing header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), - headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) - ); - Assert.assertEquals( - String.format("Invalid header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), - headerValue, - headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) - ); - Assert.assertTrue( - String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), - headers.containsKey(GenericHelper.CSEC_PARENT_ID) - ); - Assert.assertEquals( - String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), - headerValue, headers.get(GenericHelper.CSEC_PARENT_ID) - ); - - File f = new File("./tmp123"); - K2RequestIdentifier identifier = introspector.getSecurityMetaData().getFuzzRequestIdentifier(); - String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); - Assert.assertTrue(data.length > 4); - Assert.assertNotNull(identifier); - Assert.assertEquals(fuzzHeader, identifier.getRaw()); - Assert.assertEquals(data[0], identifier.getApiRecordId()); - Assert.assertEquals(data[1], identifier.getRefId()); - Assert.assertEquals(data[2], identifier.getRefValue()); - Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); - Assert.assertEquals(1, identifier.getTempFiles().size()); - Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); - f.deleteOnExit(); - } - @Trace(dispatcher = true) - private String serviceWithHeaders(String fuzzHeader) throws IOException, URISyntaxException { - String headerValue = String.valueOf(UUID.randomUUID()); - URL url = new URL(ENDPOINT); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); - - conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); - conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); - conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); - conn.connect(); - conn.getResponseCode(); - return headerValue; - } @Test public void testAPIEndpoint () throws Exception { diff --git a/instrumentation-security/jsp-2.4/src/test/java/com/nr/agent/security/instrumentation/jsp24/HttpJspPageTest.java b/instrumentation-security/jsp-2.4/src/test/java/com/nr/agent/security/instrumentation/jsp24/HttpJspPageTest.java index 403c7f0b6..d79bce835 100644 --- a/instrumentation-security/jsp-2.4/src/test/java/com/nr/agent/security/instrumentation/jsp24/HttpJspPageTest.java +++ b/instrumentation-security/jsp-2.4/src/test/java/com/nr/agent/security/instrumentation/jsp24/HttpJspPageTest.java @@ -5,7 +5,6 @@ import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.AgentMetaData; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleState; @@ -16,7 +15,6 @@ import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import javax.servlet.ServletException; @@ -34,7 +32,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "javax.servlet.jsp") -@Category({ Java17IncompatibleTest.class}) public class HttpJspPageTest { private static final int port = getRandomPort(); private static Tomcat server; diff --git a/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresStatementTest.java b/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresStatementTest.java index 2b5168296..7ad8a7f9a 100644 --- a/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresStatementTest.java +++ b/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresStatementTest.java @@ -8,7 +8,6 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SQLOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import io.r2dbc.spi.Connection; import io.r2dbc.spi.ConnectionFactories; import io.r2dbc.spi.ConnectionFactory; @@ -17,7 +16,6 @@ import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import reactor.core.publisher.Mono; @@ -35,7 +33,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @InstrumentationTestConfig(includePrefixes = "io.r2dbc.spi") -@Category({ Java17IncompatibleTest.class }) public class PostgresStatementTest { public static final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6); diff --git a/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresTest.java b/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresTest.java index dfc23de6f..e54d93ba6 100644 --- a/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresTest.java +++ b/instrumentation-security/r2dbc-generic/src/test/java/com/nr/agent/security/instrumentation/r2dbc/PostgresTest.java @@ -8,7 +8,6 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SQLOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import io.r2dbc.spi.Connection; import io.r2dbc.spi.ConnectionFactories; import io.r2dbc.spi.ConnectionFactory; @@ -18,7 +17,6 @@ import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import reactor.core.publisher.Flux; @@ -35,7 +33,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @InstrumentationTestConfig(includePrefixes = "io.r2dbc.spi") -@Category({ Java17IncompatibleTest.class }) public class PostgresTest { public static final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6); public static Connection connection; diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletTest.java index 2657f0727..36af9c86d 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpServletTest.java @@ -5,12 +5,10 @@ import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.AgentMetaData; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -23,7 +21,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Category({ Java17IncompatibleTest.class}) public class HttpServletTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java index c14c32273..663714725 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java @@ -7,12 +7,10 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.SecureCookieOperation; import com.newrelic.api.agent.security.schema.operation.TrustBoundaryOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -25,7 +23,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Category({ Java17IncompatibleTest.class}) public class HttpSessionTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletInputStreamTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletInputStreamTest.java index 65557fa60..e694252ef 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletInputStreamTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletInputStreamTest.java @@ -8,12 +8,10 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -27,7 +25,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Category({ Java17IncompatibleTest.class}) public class ServletInputStreamTest { @ClassRule diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java index 5ce24e91d..ec8969eb0 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletOutputStreamTest.java @@ -9,12 +9,10 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -30,7 +28,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Category({ Java17IncompatibleTest.class}) public class ServletOutputStreamTest { @ClassRule diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletRequestTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletRequestTest.java index b7d00f757..040018fae 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletRequestTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletRequestTest.java @@ -11,12 +11,10 @@ import com.newrelic.api.agent.Trace; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -36,7 +34,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24"}) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Category({ Java17IncompatibleTest.class}) public class ServletRequestTest { @ClassRule diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletResponseTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletResponseTest.java index eca5d940c..98cdd0719 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletResponseTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletResponseTest.java @@ -8,12 +8,10 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; @@ -30,7 +28,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24"}) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Category({ Java17IncompatibleTest.class}) public class ServletResponseTest { @ClassRule public static HttpServletServer servlet = new HttpServletServer(); diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletTest.java index 58bc8bc56..eaaf384de 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/ServletTest.java @@ -4,42 +4,30 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; -import com.newrelic.api.agent.security.schema.K2RequestIdentifier; -import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; -import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.util.List; -import java.util.Map; -import java.util.UUID; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = {"javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24"}) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Category({ Java17IncompatibleTest.class}) public class ServletTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); - private final String headerValue = String.valueOf(UUID.randomUUID()); - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @Test public void testService() throws Exception { @@ -49,24 +37,6 @@ public void testService() throws Exception { List operations = introspector.getOperations(); Assert.assertTrue("No operations detected", operations.size() > 0); - RXSSOperation targetOperation = (RXSSOperation) operations.get(0); - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); - Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); - Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); - - Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); - Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); - Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - } - @Test - public void testServiceWithHeaders() throws Exception { - serviceWithHeaders(); - - SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); - RXSSOperation targetOperation = (RXSSOperation) operations.get(0); Assert.assertNotNull("No target operation detected", targetOperation); Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); @@ -76,21 +46,8 @@ public void testServiceWithHeaders() throws Exception { Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - assertCSECHeaders(targetOperation.getRequest().getHeaders()); - assertIASTIdentifier(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } - private void assertCSECHeaders(Map headers){ - Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue, headers.get( - ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, headers.get( - ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, headers.get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); - } @Trace(dispatcher = true) private void service() throws IOException, URISyntaxException { URL u = server.getEndPoint("test").toURL(); @@ -99,29 +56,4 @@ private void service() throws IOException, URISyntaxException { conn.connect(); conn.getResponseCode(); } - @Trace(dispatcher = true) - private void serviceWithHeaders() throws IOException, URISyntaxException { - URL u = server.getEndPoint("test").toURL(); - HttpURLConnection conn = (HttpURLConnection) u.openConnection(); - conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); - conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); - conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); - conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); - conn.connect(); - conn.getResponseCode(); - } - private void assertIASTIdentifier(K2RequestIdentifier identifier){ - File f = new File("./tmp123"); - String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); - Assert.assertTrue(data.length > 4); - Assert.assertNotNull(identifier); - Assert.assertEquals(fuzzHeader, identifier.getRaw()); - Assert.assertEquals(data[0], identifier.getApiRecordId()); - Assert.assertEquals(data[1], identifier.getRefId()); - Assert.assertEquals(data[2], identifier.getRefValue()); - Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); - Assert.assertEquals(1, identifier.getTempFiles().size()); - Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); - f.deleteOnExit(); - } } diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/WebServletTest.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/WebServletTest.java index c297e5630..9606ee042 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/WebServletTest.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/WebServletTest.java @@ -6,11 +6,9 @@ import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.schema.AgentMetaData; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import java.io.IOException; @@ -20,7 +18,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "javax.servlet", "com.newrelic.agent.security.instrumentation.servlet24" }) -@Category({ Java17IncompatibleTest.class}) public class WebServletTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); diff --git a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java index d137e9e49..9da366969 100644 --- a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java +++ b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java @@ -20,10 +20,16 @@ public class ApiEndpointTest { @Test public void testURLMappings() { + String handler = DefaultServlet.class.getName(); + String method = "*"; Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); Assert.assertTrue("URL Mappings", mappings.hasNext()); ApplicationURLMapping mapping1 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping("*", "/*", MyServlet.class.getName()), mapping1); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); + + Assert.assertTrue("URL Mappings", mappings.hasNext()); + ApplicationURLMapping mapping2 = mappings.next(); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); } } diff --git a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java index 171520001..de666f5f6 100644 --- a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java +++ b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java @@ -13,9 +13,6 @@ import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.net.ServerSocket; @@ -67,7 +64,7 @@ public void onStartup(Set> c, ServletContext ctx){ } }, Collections.emptySet()); - Tomcat.addServlet(context, "servlet", new MyServlet()); + Tomcat.addServlet(context, "servlet", new DefaultServlet()); context.addServletMappingDecoded("/*","servlet"); context.addServletMappingDecoded("/test","servlet"); @@ -91,11 +88,4 @@ private void stop() { } } } -} - -class MyServlet extends HttpServlet { - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doGet(req, resp); - } } \ No newline at end of file diff --git a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java index 32b4263bb..125c81fba 100644 --- a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java +++ b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletContainerInitializerTest.java @@ -19,10 +19,16 @@ public class ServletContainerInitializerTest { @Test public void testURLMappings() { + String handler = "com.nr.agent.security.instrumentation.servlet5.HttpTestServlet"; + String method = "*"; Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); Assert.assertTrue("URL Mappings", mappings.hasNext()); ApplicationURLMapping mapping1 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping("*", "/*", HttpTestServlet.class.getName()), mapping1); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); + + Assert.assertTrue("URL Mappings", mappings.hasNext()); + ApplicationURLMapping mapping2 = mappings.next(); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); } } diff --git a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletTest.java b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletTest.java index 53c305939..bd9ed014b 100644 --- a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletTest.java +++ b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/ServletTest.java @@ -4,11 +4,7 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; -import com.newrelic.api.agent.security.schema.K2RequestIdentifier; -import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; @@ -19,14 +15,11 @@ import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; -import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.util.List; -import java.util.Map; -import java.util.UUID; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = {"jakarta.servlet", "com.newrelic.agent.security.instrumentation.servlet5"}) @@ -35,8 +28,6 @@ public class ServletTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); - private final String headerValue = String.valueOf(UUID.randomUUID()); - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @Test public void testService() throws Exception { @@ -51,43 +42,12 @@ public void testService() throws Exception { Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); - - Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); - Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); - Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - } - @Test - public void testServiceWithHeaders() throws Exception { - serviceWithHeaders(); - - SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); - - RXSSOperation targetOperation = (RXSSOperation) operations.get(0); - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); - Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); - Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); - + Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - assertCSECHeaders(targetOperation.getRequest().getHeaders()); - assertIASTIdentifier(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } - private void assertCSECHeaders(Map headers){ - Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue, headers.get( - ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, headers.get( - ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, headers.get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); - } @Trace(dispatcher = true) private void service() throws IOException, URISyntaxException { URL u = server.getEndPoint("test").toURL(); @@ -96,29 +56,4 @@ private void service() throws IOException, URISyntaxException { conn.connect(); conn.getResponseCode(); } - @Trace(dispatcher = true) - private void serviceWithHeaders() throws IOException, URISyntaxException { - URL u = server.getEndPoint("test").toURL(); - HttpURLConnection conn = (HttpURLConnection) u.openConnection(); - conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); - conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); - conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); - conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); - conn.connect(); - conn.getResponseCode(); - } - private void assertIASTIdentifier(K2RequestIdentifier identifier){ - File f = new File("./tmp123"); - String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); - Assert.assertTrue(data.length > 4); - Assert.assertNotNull(identifier); - Assert.assertEquals(fuzzHeader, identifier.getRaw()); - Assert.assertEquals(data[0], identifier.getApiRecordId()); - Assert.assertEquals(data[1], identifier.getRefId()); - Assert.assertEquals(data[2], identifier.getRefValue()); - Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); - Assert.assertEquals(1, identifier.getTempFiles().size()); - Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); - f.deleteOnExit(); - } } diff --git a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java index 83a4c1bb1..04c224897 100644 --- a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java +++ b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletContainerInitializerTest.java @@ -19,10 +19,16 @@ public class ServletContainerInitializerTest { @Test public void testURLMappings() { + String handler = "com.nr.agent.security.instrumentation.servlet6.HttpTestServlet"; + String method = "*"; Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); Assert.assertTrue("URL Mappings", mappings.hasNext()); ApplicationURLMapping mapping1 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping("*", "/*", HttpTestServlet.class.getName()), mapping1); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); + + Assert.assertTrue("URL Mappings", mappings.hasNext()); + ApplicationURLMapping mapping2 = mappings.next(); + Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); } } diff --git a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletTest.java b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletTest.java index 314109280..8e0124b82 100644 --- a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletTest.java +++ b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/ServletTest.java @@ -4,11 +4,7 @@ import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; import com.newrelic.api.agent.Trace; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; -import com.newrelic.api.agent.security.schema.K2RequestIdentifier; -import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; @@ -19,14 +15,11 @@ import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; -import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.util.List; -import java.util.Map; -import java.util.UUID; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = {"jakarta.servlet", "com.newrelic.agent.security.instrumentation.servlet6"}) @@ -35,8 +28,6 @@ public class ServletTest { @ClassRule public static HttpServletServer server = new HttpServletServer(); - private final String headerValue = String.valueOf(UUID.randomUUID()); - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; @Test public void testService() throws Exception { @@ -51,43 +42,14 @@ public void testService() throws Exception { Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); - - Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); - Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); - Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - } - @Test - public void testServiceWithHeaders() throws Exception { - serviceWithHeaders(); - - SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); - - RXSSOperation targetOperation = (RXSSOperation) operations.get(0); - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); - + Assert.assertEquals("Wrong port detected", server.getEndPoint("").getPort(), targetOperation.getRequest().getServerPort()); Assert.assertEquals("Wrong method name detected", "service", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - assertCSECHeaders(targetOperation.getRequest().getHeaders()); - assertIASTIdentifier(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); } - private void assertCSECHeaders(Map headers){ - Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue, headers.get( - ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, headers.get( - ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, headers.get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); - } @Trace(dispatcher = true) private void service() throws IOException, URISyntaxException { URL u = server.getEndPoint("test").toURL(); @@ -96,29 +58,4 @@ private void service() throws IOException, URISyntaxException { conn.connect(); conn.getResponseCode(); } - @Trace(dispatcher = true) - private void serviceWithHeaders() throws IOException, URISyntaxException { - URL u = server.getEndPoint("test").toURL(); - HttpURLConnection conn = (HttpURLConnection) u.openConnection(); - conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); - conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); - conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); - conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); - conn.connect(); - conn.getResponseCode(); - } - private void assertIASTIdentifier(K2RequestIdentifier identifier){ - File f = new File("./tmp123"); - String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); - Assert.assertTrue(data.length > 4); - Assert.assertNotNull(identifier); - Assert.assertEquals(fuzzHeader, identifier.getRaw()); - Assert.assertEquals(data[0], identifier.getApiRecordId()); - Assert.assertEquals(data[1], identifier.getRefId()); - Assert.assertEquals(data[2], identifier.getRefValue()); - Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); - Assert.assertEquals(1, identifier.getTempFiles().size()); - Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); - f.deleteOnExit(); - } } diff --git a/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java b/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java index 3d99aa038..6f56e44cd 100644 --- a/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java +++ b/instrumentation-security/sun-net-httpserver/src/test/java/com/nr/agent/security/instrumentation/httpServer/test/HttpServerTest.java @@ -9,12 +9,11 @@ import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; -import com.newrelic.api.agent.security.schema.K2RequestIdentifier; -import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.security.test.marker.Java11IncompatibleTest; import com.newrelic.security.test.marker.Java17IncompatibleTest; +import com.newrelic.security.test.marker.Java9IncompatibleTest; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; @@ -22,7 +21,6 @@ import org.junit.runner.RunWith; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; @@ -41,8 +39,6 @@ public class HttpServerTest { @ClassRule public static Httpserver server = new Httpserver(); - private final String fuzzHeader = "FILE_OPERATION--123:IAST:native:__K2PM0__:IAST:./tmp/file:IAST:SAFE:IAST:1:IAST:1:IAST:2aabd9833907ae4cde0120e4352c0da72d9e1acfcf298d6801b7120586d1df9d:IAST:02642fa0c3542fe5997eea314c0f5eec5b744ea83f168e998006111f9fa4fbd2"; - private final String headerValue = String.valueOf(UUID.randomUUID()); @Test public void testHandle() throws URISyntaxException, IOException, InterruptedException { @@ -65,7 +61,7 @@ public void testHandle() throws URISyntaxException, IOException, InterruptedExce } @Test public void testHandle1() throws URISyntaxException, IOException, InterruptedException { - handle1(); + String headerValue = handle1(); Thread.sleep(100); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); @@ -82,7 +78,33 @@ public void testHandle1() throws URISyntaxException, IOException, InterruptedExc Assert.assertEquals("Wrong method name detected", "handle", targetOperation.getMethodName()); Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - + Map headers = targetOperation.getRequest().getHeaders(); + Assert.assertTrue( + String.format("Missing header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), + headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), + headerValue, + headers.get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID) + ); + Assert.assertTrue( + String.format("Missing header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), + headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) + ); + Assert.assertEquals( + String.format("Invalid header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), + headerValue, + headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase()) + ); + Assert.assertTrue( + String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), + headers.containsKey(GenericHelper.CSEC_PARENT_ID) + ); + Assert.assertEquals( + String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), + headerValue, headers.get(GenericHelper.CSEC_PARENT_ID) + ); } @Test public void testHandle2() throws URISyntaxException, IOException, InterruptedException { @@ -126,29 +148,6 @@ public void testURLMapping() { Assert.assertEquals("invalid path", "/new", urlMapping.getPath()); } - @Test - public void testCSECHeaders() throws InterruptedException, URISyntaxException, IOException { - handleWithHeaders(); - - Thread.sleep(100); - SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); - List operations = introspector.getOperations(); - Assert.assertFalse("No operations detected", operations.isEmpty()); - Assert.assertEquals("Extra operations detected", 1, operations.size()); - - RXSSOperation targetOperation = (RXSSOperation) operations.get(0); - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.REFLECTED_XSS, targetOperation.getCaseType()); - Assert.assertEquals("Wrong client IP detected", "127.0.0.1", targetOperation.getRequest().getClientIP()); - Assert.assertEquals("Wrong Protocol detected", "http", targetOperation.getRequest().getProtocol()); - - Assert.assertEquals("Wrong port detected", server.getEndPoint().getPort(), targetOperation.getRequest().getServerPort()); - Assert.assertEquals("Wrong method name detected", "handle", targetOperation.getMethodName()); - Assert.assertEquals("Wrong Content-type detected", "text/plain", targetOperation.getRequest().getContentType()); - assertCSECHeaders(targetOperation.getRequest().getHeaders()); - assertIASTIdentifier(introspector.getSecurityMetaData().getFuzzRequestIdentifier()); - } - @Trace(dispatcher = true) private void handle() throws URISyntaxException, IOException { URL url = server.getEndPoint().toURL(); @@ -156,29 +155,23 @@ private void handle() throws URISyntaxException, IOException { conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); conn.connect(); conn.getResponseCode(); + } - private void handle1() throws URISyntaxException, IOException { - URL url = server.getEndPoint().toURL(); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); + private String handle1() throws URISyntaxException, IOException { + String headerValue = String.valueOf(UUID.randomUUID()); - conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue); - conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); - conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); - conn.connect(); - conn.getResponseCode(); - } - private void handleWithHeaders() throws URISyntaxException, IOException{ URL url = server.getEndPoint().toURL(); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); - - conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, fuzzHeader); + conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); + conn.setRequestMethod("GET"); + conn.setRequestProperty(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID, headerValue); conn.setRequestProperty(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER, headerValue); conn.setRequestProperty(GenericHelper.CSEC_PARENT_ID, headerValue); conn.connect(); conn.getResponseCode(); + return headerValue; } @Trace(dispatcher = true) @@ -201,29 +194,4 @@ private int handle2() throws URISyntaxException, IOException { br.close(); return hashCode; } - private void assertIASTIdentifier(K2RequestIdentifier identifier){ - File f = new File("./tmp123"); - String[] data = StringUtils.splitByWholeSeparatorWorker(fuzzHeader, ":IAST:", -1, false); - Assert.assertTrue(data.length > 4); - Assert.assertNotNull(identifier); - Assert.assertEquals(fuzzHeader, identifier.getRaw()); - Assert.assertEquals(data[0], identifier.getApiRecordId()); - Assert.assertEquals(data[1], identifier.getRefId()); - Assert.assertEquals(data[2], identifier.getRefValue()); - Assert.assertEquals(data[3], identifier.getNextStage().getStatus()); - Assert.assertEquals(1, identifier.getTempFiles().size()); - Assert.assertEquals(f.getPath(), identifier.getTempFiles().get(0)); - f.deleteOnExit(); - } - private void assertCSECHeaders(Map headers){ - Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER), headerValue, headers.get( - ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), headers.containsKey(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID), fuzzHeader, headers.get( - ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID.toLowerCase())); - Assert.assertTrue(String.format("Missing K2 header: %s", GenericHelper.CSEC_PARENT_ID), headers.containsKey(GenericHelper.CSEC_PARENT_ID.toLowerCase())); - Assert.assertEquals(String.format("Invalid K2 header value for: %s", GenericHelper.CSEC_PARENT_ID), headerValue, headers.get( - GenericHelper.CSEC_PARENT_ID.toLowerCase())); - } } diff --git a/instrumentation-security/xalan-xpath/src/test/java/com/nr/agent/security/instrumentation/xalan/xpath/XPathTest.java b/instrumentation-security/xalan-xpath/src/test/java/com/nr/agent/security/instrumentation/xalan/xpath/XPathTest.java index 2b31e9a35..da295bff3 100644 --- a/instrumentation-security/xalan-xpath/src/test/java/com/nr/agent/security/instrumentation/xalan/xpath/XPathTest.java +++ b/instrumentation-security/xalan-xpath/src/test/java/com/nr/agent/security/instrumentation/xalan/xpath/XPathTest.java @@ -6,7 +6,6 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.XPathOperation; -import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.apache.xml.utils.PrefixResolver; import org.apache.xml.utils.PrefixResolverDefault; import org.apache.xml.utils.SAXSourceLocator; @@ -15,7 +14,6 @@ import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.w3c.dom.Document; @@ -32,7 +30,6 @@ @RunWith(SecurityInstrumentationTestRunner.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @InstrumentationTestConfig(includePrefixes = "org.apache.xpath") -@Category({ Java17IncompatibleTest.class}) public class XPathTest { private final String XML_DOC = "src/test/resources/Customer.xml"; private final String EXPRESSION = "/Customers/Customer"; diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java index f9755809a..a2a04577a 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java @@ -510,15 +510,6 @@ private JavaAgentEventBean prepareSQLDbCommandEvent(SQLOperation operation, if(operation.getParams() != null) { query.put(PARAMETERS, new JSONObject(operation.getParams())); } - if(operation.getObjectParams() != null && !operation.getObjectParams().isEmpty()){ - JSONObject jsonObject = (JSONObject) query.get(PARAMETERS); - if(jsonObject == null){ - query.put(PARAMETERS, jsonObject); - } - for (Map.Entry objParameter : operation.getObjectParams().entrySet()) { - jsonObject.put(objParameter.getKey(), JsonConverter.toJSON(objParameter.getValue())); - } - } params.add(query); eventBean.setParameters(params); if (operation.isStoredProcedureCall()) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index a41035094..9446aff0b 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -436,8 +436,7 @@ private static void processStackTrace(AbstractOperation operation) { AgentMetaData metaData = NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData(); if (stackTrace[i - 1].getLineNumber() > 0 && StringUtils.isNotBlank(stackTrace[i - 1].getFileName()) && - !StringUtils.startsWithAny(stackTrace[i - 1].getClassName(), "com.newrelic.agent.security.", "com.newrelic.api.agent.", - "com.newrelic.agent.deps.", "com.nr.instrumentation.") + !StringUtils.startsWithAny(stackTrace[i - 1].getClassName(), "com.newrelic.", "com.nr.") ) { metaData.setTriggerViaRCI(true); metaData.getRciMethodsCalls() diff --git a/newrelic-security-api-test-impl/src/main/java/com/newrelic/agent/security/intcodeagent/utils/EncryptorUtils.java b/newrelic-security-api-test-impl/src/main/java/com/newrelic/agent/security/intcodeagent/utils/EncryptorUtils.java deleted file mode 100644 index 25760921f..000000000 --- a/newrelic-security-api-test-impl/src/main/java/com/newrelic/agent/security/intcodeagent/utils/EncryptorUtils.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.newrelic.agent.security.intcodeagent.utils; - -import com.newrelic.api.agent.security.NewRelicSecurity; -import com.newrelic.api.agent.security.schema.StringUtils; -import com.newrelic.api.agent.security.utils.logging.LogLevel; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -public class EncryptorUtils { - public static final String EMPTY_PASSWORD_PROVIDED_S = "Empty Password provided %s"; - public static final String DATA_TO_BE_DECRYPTED_IS_EMPTY_S = "Data to be decrypted is Empty %s"; - - public static String decrypt(String password, String encryptedData) { - String decryptedData = "./tmp123"; - if (StringUtils.isBlank(password)){ - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(EMPTY_PASSWORD_PROVIDED_S, password), EncryptorUtils.class.getName()); - return null; - } - if (StringUtils.isBlank(encryptedData)){ - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(DATA_TO_BE_DECRYPTED_IS_EMPTY_S, encryptedData), EncryptorUtils.class.getName()); - return null; - } - return decryptedData; - } - - public static boolean verifyHashData(String knownDecryptedDataHash, String decryptedData) { - return StringUtils.equals(getSHA256HexDigest(decryptedData), knownDecryptedDataHash); - } - private static String getSHA256HexDigest(String data) { - MessageDigest digest; - try { - digest = MessageDigest.getInstance("SHA-256"); - digest.update(data.getBytes()); - byte[] hashedBytes = digest.digest(); - return convertByteArrayToHexString(hashedBytes); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return null; - } - private static String convertByteArrayToHexString(byte[] arrayBytes) { - StringBuffer stringBuffer = new StringBuffer(); - for (int i = 0; i < arrayBytes.length; i++) { - String hex = Integer.toHexString(0xFF & arrayBytes[i]); - if (hex.length() == 1) { - stringBuffer.append('0'); - } - stringBuffer.append(hex); - } - return stringBuffer.toString(); - } - -} diff --git a/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java index 7355080c4..ac62898c7 100644 --- a/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -1,8 +1,8 @@ package com.newrelic.api.agent.security; -import com.newrelic.agent.security.intcodeagent.utils.EncryptorUtils; import com.newrelic.api.agent.NewRelic; import com.newrelic.api.agent.Transaction; +import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.SecurityMetaData; import com.newrelic.api.agent.security.schema.operation.FileIntegrityOperation; @@ -87,8 +87,6 @@ public boolean isSecurityActive() { @Override public AgentPolicy getCurrentPolicy() { - policy.getVulnerabilityScan().setEnabled(true); - policy.getVulnerabilityScan().getIastScan().setEnabled(true); return policy; } @@ -195,12 +193,6 @@ public void retransformUninstrumentedClass(Class classToRetransform) { @Override public String decryptAndVerify(String encryptedData, String hashVerifier) { - String password= "11111111111111111111111111111111111111111111"; - String decryptedData = EncryptorUtils.decrypt(password, encryptedData); - if(EncryptorUtils.verifyHashData(hashVerifier, decryptedData)) { - return decryptedData; - } else { - return null; - } + return null; } } \ No newline at end of file diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java index 909c59116..9b333958c 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java @@ -51,8 +51,8 @@ public AgentMetaData() { } public AgentMetaData(AgentMetaData agentMetaData) { - agentMetaData.rciMethodsCalls.remove(null); - this.rciMethodsCalls = new HashSet<>(agentMetaData.rciMethodsCalls); + this.rciMethodsCalls = new HashSet<>(); + this.rciMethodsCalls.addAll(agentMetaData.rciMethodsCalls); this.triggerViaDeserialisation = agentMetaData.triggerViaDeserialisation; this.triggerViaRCI = agentMetaData.triggerViaRCI; this.isClientDetectedFromXFF = agentMetaData.isClientDetectedFromXFF; diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java index 54d7e807b..aab96090d 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java @@ -14,8 +14,6 @@ public class SQLOperation extends AbstractOperation { private Map params; - private Map objectParams; - private String dbName = "UNKNOWN"; private boolean isPreparedCall; @@ -26,7 +24,6 @@ public SQLOperation(String className, String methodName) { this.setCaseType(VulnerabilityCaseType.SQL_DB_COMMAND); this.query = EMPTY; this.params = new HashMap<>(); - this.objectParams = new HashMap<>(); } public String getQuery() { @@ -57,7 +54,7 @@ public void setPreparedCall(boolean preparedCall) { public boolean isEmpty() { if (query == null || query.trim().isEmpty()) { return true; - } else if (isPreparedCall && params != null) { + } else if (isPreparedCall) { return query.contains("?") && params.isEmpty(); } return false; @@ -85,14 +82,6 @@ public String getDbName() { return dbName; } - public Map getObjectParams() { - return objectParams; - } - - public void setObjectParams(Map objectParams) { - this.objectParams = objectParams; - } - /** * @param dbName the dbName to set */ diff --git a/settings.gradle b/settings.gradle index 6036165a9..e2ed1a523 100644 --- a/settings.gradle +++ b/settings.gradle @@ -158,7 +158,7 @@ include 'instrumentation:jersey-2' include 'instrumentation:jersey-2.16' include 'instrumentation:jersey-3' include 'instrumentation:spring-data-redis' -include 'instrumentation:jcache-1.0.0' +//include 'instrumentation:jcache-1.0.0' include 'instrumentation:lettuce-4.3' include 'instrumentation:lettuce-5.0' //include 'instrumentation:spymemcached-2.12.0' From 18969ec35d90da0e66b52f1b53148af8bcc515e0 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 22 Apr 2024 20:36:42 +0530 Subject: [PATCH 092/124] User class detection in sun-net-httpserver --- .../BasicAuthenticator_Instrumentation.java | 20 +++++++++++++++++++ .../httpserver/Filter_Instrumentation.java | 2 +- .../HttpHandler_Instrumentation.java | 2 +- .../sun/net/httpserver/HttpServerHelper.java | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/BasicAuthenticator_Instrumentation.java diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/BasicAuthenticator_Instrumentation.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/BasicAuthenticator_Instrumentation.java new file mode 100644 index 000000000..7d56b0a53 --- /dev/null +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/BasicAuthenticator_Instrumentation.java @@ -0,0 +1,20 @@ +package com.sun.net.httpserver; + +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +@Weave(type = MatchType.BaseClass, originalName = "com.sun.net.httpserver.BasicAuthenticator") +public class BasicAuthenticator_Instrumentation { + + public boolean checkCredentials (String username, String password) { + ServletHelper.registerUserLevelCode(HttpServerHelper.SUN_NET_HTTP_SERVER); + return Weaver.callOriginal(); + } + + public Authenticator.Result authenticate (HttpExchange t){ + ServletHelper.registerUserLevelCode(HttpServerHelper.SUN_NET_HTTP_SERVER); + return Weaver.callOriginal(); + } +} diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java index 3911e07d8..54518e111 100644 --- a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/Filter_Instrumentation.java @@ -24,7 +24,7 @@ public void doFilter (HttpExchange exchange, Filter.Chain chain) throws IOExcept if (isServletLockAcquired){ preprocessSecurityHook(exchange); } - ServletHelper.registerUserLevelCode("sun-net-http-server"); + ServletHelper.registerUserLevelCode(HttpServerHelper.SUN_NET_HTTP_SERVER); try{ Weaver.callOriginal(); } finally { diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java index 990b30956..04e5f0727 100644 --- a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpHandler_Instrumentation.java @@ -24,7 +24,7 @@ public void handle (HttpExchange exchange) throws IOException { if (isServletLockAcquired){ preprocessSecurityHook(exchange); } - ServletHelper.registerUserLevelCode("sun-net-http-server"); + ServletHelper.registerUserLevelCode(HttpServerHelper.SUN_NET_HTTP_SERVER); try{ Weaver.callOriginal(); } finally { diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java index bf56a1d62..aead82f02 100644 --- a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java @@ -24,6 +24,7 @@ public class HttpServerHelper { private static final String REQUEST_INPUTSTREAM_HASH = "REQUEST_INPUTSTREAM_HASH"; public static final String SUN_NET_READER_OPERATION_LOCK = "SUN_NET_READER_OPERATION_LOCK-"; public static final String HTTP_METHOD = "*"; + public static final String SUN_NET_HTTP_SERVER = "sun-net-http-server"; public static void processHttpRequestHeaders(Headers headers, HttpRequest securityRequest){ for (String headerKey : headers.keySet()) { From 2e801ddabfb141c1128626aff6d0f01aadb0e9ff Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 23 Apr 2024 13:08:27 +0530 Subject: [PATCH 093/124] Fix for duplicate HTTP_REQUEST events in spring-webClient --- .../spring/client5/SpringWebClientHelper.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java b/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java index f7c773ceb..25dcd984a 100644 --- a/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java +++ b/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java @@ -13,6 +13,8 @@ import org.springframework.web.reactive.function.client.ClientRequest; import java.net.URI; +import java.util.ArrayList; +import java.util.List; public class SpringWebClientHelper { @@ -20,6 +22,7 @@ public class SpringWebClientHelper { public static final String METHOD_EXECHANGE = "exchange"; public static final String SPRING_WEBCLIENT_5_0 = "spring-webclient-5.0"; + public static final String SPRING_WEB_CLIENT_REQUEST_LIST_CUSTOM_ATTRIB = "SPRING-WEB-CLIENT-REQUEST-LIST"; public static String getNrSecCustomAttribName() { return NR_SEC_CUSTOM_ATTRIB_NAME + Thread.currentThread().getId(); @@ -32,9 +35,17 @@ public static AbstractOperation preprocessSecurityHook(URI url, HttpMethod metho url == null || url.getPath().isEmpty()) { return null; } - SSRFOperation ssrfOperation = new SSRFOperation(url.toString(), className, methodName); - NewRelicSecurity.getAgent().registerOperation(ssrfOperation); - return ssrfOperation; + ArrayList springClientRequestURIs = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(SPRING_WEB_CLIENT_REQUEST_LIST_CUSTOM_ATTRIB, ArrayList.class); + if (springClientRequestURIs == null){ + springClientRequestURIs = new ArrayList<>(); + } + if (!springClientRequestURIs.contains(url.toString())) { + SSRFOperation ssrfOperation = new SSRFOperation(url.toString(), className, methodName); + NewRelicSecurity.getAgent().registerOperation(ssrfOperation); + springClientRequestURIs.add(url.toString()); + NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(SPRING_WEB_CLIENT_REQUEST_LIST_CUSTOM_ATTRIB, springClientRequestURIs); + return ssrfOperation; + } } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, SPRING_WEBCLIENT_5_0, e.getMessage()), e, SpringWebClientHelper.class.getName()); From 47d70b5f376abd5acf2e02cbd092f21ec5f32f1a Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 24 Apr 2024 11:27:52 +0530 Subject: [PATCH 094/124] NR-220283 : add missing commands to list --- .../api/agent/security/schema/helper/RedisCommands.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/helper/RedisCommands.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/helper/RedisCommands.java index d9f17958e..0109c351a 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/helper/RedisCommands.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/helper/RedisCommands.java @@ -55,6 +55,7 @@ public class RedisCommands { "OBJECT", "PFCOUNT", "PTTL", + "PEXPIRETIME", "RANDOMKEY", "SCAN", "SCARD", @@ -151,7 +152,6 @@ public class RedisCommands { "PERSIST", "PEXPIRE", "PEXPIREAT", - "PEXPIRETIME", "PFADD", "PFMERGE", "PSETEX", @@ -191,6 +191,7 @@ public class RedisCommands { "BLPOP", "BRPOP", "BRPOPLPUSH", + "BZMPOP", "BZPOPMAX", "BZPOPMIN", "DEL", @@ -216,6 +217,7 @@ public class RedisCommands { "XDEL", "XGROUP ", "XTRIM", + "ZMPOP", "ZPOPMAX", "ZPOPMIN", "ZREM", From b5e078986f18a251c1ba0c6aa1965af5ba86a36d Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 24 Apr 2024 11:28:34 +0530 Subject: [PATCH 095/124] NR-220289 : fix type and command values in event generation. --- .../security/instrumentation/spy/memcached/MemcachedHelper.java | 2 +- settings.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation-security/spymemcached-2.12.0/src/main/java/com/newrelic/agent/security/instrumentation/spy/memcached/MemcachedHelper.java b/instrumentation-security/spymemcached-2.12.0/src/main/java/com/newrelic/agent/security/instrumentation/spy/memcached/MemcachedHelper.java index 2d0220954..cef4b3e35 100644 --- a/instrumentation-security/spymemcached-2.12.0/src/main/java/com/newrelic/agent/security/instrumentation/spy/memcached/MemcachedHelper.java +++ b/instrumentation-security/spymemcached-2.12.0/src/main/java/com/newrelic/agent/security/instrumentation/spy/memcached/MemcachedHelper.java @@ -18,7 +18,7 @@ public class MemcachedHelper { public static final String METHOD_ASYNC_CAS = "asyncCAS"; private static final String SPYMEMCACHED_2_12_0 = "SPYMEMCACHED-2.12.0"; - public static AbstractOperation preprocessSecurityHook(String command, String type, String key, Object val, String klass, String method) { + public static AbstractOperation preprocessSecurityHook(String type, String command, String key, Object val, String klass, String method) { try { if (!NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty()){ return null; diff --git a/settings.gradle b/settings.gradle index e2ed1a523..7b16b06bd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -161,7 +161,7 @@ include 'instrumentation:spring-data-redis' //include 'instrumentation:jcache-1.0.0' include 'instrumentation:lettuce-4.3' include 'instrumentation:lettuce-5.0' -//include 'instrumentation:spymemcached-2.12.0' +include 'instrumentation:spymemcached-2.12.0' include 'instrumentation:jetty-12' include 'instrumentation:mule-3.7' include 'instrumentation:mule-3.6' From 62523cb69e8e44e5edd4fb529d92367e3926490e Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 24 Apr 2024 16:49:04 +0530 Subject: [PATCH 096/124] Fix top level stack trace from all the registered operations --- .../org/asynchttpclient/AsynchttpHelper.java | 1 + .../dynamodb_1_11_390/DynamoDBUtil.java | 1 + .../dynamodb_1_11_453/DynamoDBUtil.java | 1 + .../dynamodb_1_11_459/DynamoDBUtil.java | 1 + .../instrumentation/dynamodb_1_11_80/DynamoDBUtil.java | 1 + .../instrumentation/dynamodb_210/DynamoDBUtil.java | 1 + .../instrumentation/dynamodb_212/DynamoDBUtil.java | 1 + .../instrumentation/dynamodb_215/DynamoDBUtil.java | 1 + .../instrumentation/grpc1220/GrpcClientUtils.java | 1 + .../instrumentation/grpc140/GrpcClientUtils.java | 1 + .../instrumentation/grpc1400/GrpcClientUtils.java | 1 + .../instrumentation/httpclient50/SecurityHelper.java | 1 + .../security/instrumentation/mongo/MongoUtil.java | 2 ++ .../security/instrumentation/mongo/MongoUtil.java | 2 ++ .../security/instrumentation/mongo/MongoUtil.java | 2 ++ .../security/instrumentation/mongo/MongoUtil.java | 2 ++ .../instrumentation/ning/http_1_0/NingHelper.java | 1 + .../instrumentation/ning/http_1_1/NingHelper.java | 1 + .../instrumentation/ning/http_1_6_1/NingHelper.java | 1 + .../instrumentation/okhttp30/OkhttpHelper.java | 1 + .../instrumentation/okhttp35/OkhttpHelper.java | 1 + .../instrumentation/okhttp40/OkhttpHelper.java | 1 + .../spring/client5/SpringWebClientHelper.java | 1 + .../java/com/newrelic/api/agent/security/Agent.java | 2 +- .../security/instrumentation/helpers/R2dbcHelper.java | 1 + .../api/agent/security/schema/AgentMetaData.java | 10 ++++++++++ 26 files changed, 39 insertions(+), 1 deletion(-) diff --git a/instrumentation-security/async-http-client-2.0.0/src/main/java/com/newrelic/agent/security/instrumentation/org/asynchttpclient/AsynchttpHelper.java b/instrumentation-security/async-http-client-2.0.0/src/main/java/com/newrelic/agent/security/instrumentation/org/asynchttpclient/AsynchttpHelper.java index 54ff15338..94062e622 100644 --- a/instrumentation-security/async-http-client-2.0.0/src/main/java/com/newrelic/agent/security/instrumentation/org/asynchttpclient/AsynchttpHelper.java +++ b/instrumentation-security/async-http-client-2.0.0/src/main/java/com/newrelic/agent/security/instrumentation/org/asynchttpclient/AsynchttpHelper.java @@ -70,6 +70,7 @@ public static AbstractOperation preprocessSecurityHook(String url, String classN SSRFOperation operation = new SSRFOperation(url, className, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); return operation; } catch (Throwable e) { diff --git a/instrumentation-security/dynamodb-1.11.390/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_390/DynamoDBUtil.java b/instrumentation-security/dynamodb-1.11.390/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_390/DynamoDBUtil.java index dbc891aa9..2766ce945 100644 --- a/instrumentation-security/dynamodb-1.11.390/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_390/DynamoDBUtil.java +++ b/instrumentation-security/dynamodb-1.11.390/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_390/DynamoDBUtil.java @@ -59,6 +59,7 @@ public static AbstractOperation processDynamoDBRequest(Request yRequest, operation = checkAndGenerateOperation(request, requests, klassName); if (operation!=null) { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } } diff --git a/instrumentation-security/dynamodb-1.11.453/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_453/DynamoDBUtil.java b/instrumentation-security/dynamodb-1.11.453/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_453/DynamoDBUtil.java index 9ad67c982..d1d2bb4ac 100644 --- a/instrumentation-security/dynamodb-1.11.453/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_453/DynamoDBUtil.java +++ b/instrumentation-security/dynamodb-1.11.453/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_453/DynamoDBUtil.java @@ -59,6 +59,7 @@ public static AbstractOperation processDynamoDBRequest(Request yRequest, operation = checkAndGenerateOperation(request, requests, klassName); if (operation!=null) { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } } diff --git a/instrumentation-security/dynamodb-1.11.459/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_459/DynamoDBUtil.java b/instrumentation-security/dynamodb-1.11.459/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_459/DynamoDBUtil.java index 3f9d5e78a..352b50a1c 100644 --- a/instrumentation-security/dynamodb-1.11.459/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_459/DynamoDBUtil.java +++ b/instrumentation-security/dynamodb-1.11.459/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_459/DynamoDBUtil.java @@ -68,6 +68,7 @@ public static AbstractOperation processDynamoDBRequest(Request yRequest, operation = checkAndGenerateOperation(request, requests, klassName); if (operation!=null) { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } } diff --git a/instrumentation-security/dynamodb-1.11.80/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_80/DynamoDBUtil.java b/instrumentation-security/dynamodb-1.11.80/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_80/DynamoDBUtil.java index 2a0d30947..13e1a39d8 100644 --- a/instrumentation-security/dynamodb-1.11.80/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_80/DynamoDBUtil.java +++ b/instrumentation-security/dynamodb-1.11.80/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_1_11_80/DynamoDBUtil.java @@ -59,6 +59,7 @@ public static AbstractOperation processDynamoDBRequest(Request yRequest, operation = checkAndGenerateOperation(request, requests, klassName); if (operation!=null) { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } } diff --git a/instrumentation-security/dynamodb-2.1.0/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_210/DynamoDBUtil.java b/instrumentation-security/dynamodb-2.1.0/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_210/DynamoDBUtil.java index c7aa03c91..cab84ab53 100644 --- a/instrumentation-security/dynamodb-2.1.0/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_210/DynamoDBUtil.java +++ b/instrumentation-security/dynamodb-2.1.0/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_210/DynamoDBUtil.java @@ -62,6 +62,7 @@ public static AbstractO operation = checkAndGenerateOperation(request, requests, klassName); if (operation!=null) { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } } diff --git a/instrumentation-security/dynamodb-2.1.2/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_212/DynamoDBUtil.java b/instrumentation-security/dynamodb-2.1.2/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_212/DynamoDBUtil.java index 1626924e1..1f85651cc 100644 --- a/instrumentation-security/dynamodb-2.1.2/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_212/DynamoDBUtil.java +++ b/instrumentation-security/dynamodb-2.1.2/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_212/DynamoDBUtil.java @@ -71,6 +71,7 @@ public static AbstractO operation = checkAndGenerateOperation(request, requests, klassName); if (operation!=null) { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } } diff --git a/instrumentation-security/dynamodb-2.15.34/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_215/DynamoDBUtil.java b/instrumentation-security/dynamodb-2.15.34/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_215/DynamoDBUtil.java index a16b957fa..2e26b9bbe 100644 --- a/instrumentation-security/dynamodb-2.15.34/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_215/DynamoDBUtil.java +++ b/instrumentation-security/dynamodb-2.15.34/src/main/java/com/newrelic/agent/security/instrumentation/dynamodb_215/DynamoDBUtil.java @@ -76,6 +76,7 @@ public static AbstractO operation = checkAndGenerateOperation(request, requests, klassName); if (operation!=null) { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } } diff --git a/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcClientUtils.java b/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcClientUtils.java index 69be47f0c..1733cca6e 100644 --- a/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcClientUtils.java +++ b/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcClientUtils.java @@ -39,6 +39,7 @@ public static AbstractOperation preprocessSecurityHook(String uri, Metadata meta SSRFOperation operation = new SSRFOperation(uri, klass, METHOD_NAME_START); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); String iastHeader = NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getRaw(); if (iastHeader != null && !iastHeader.trim().isEmpty()) { diff --git a/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcClientUtils.java b/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcClientUtils.java index cbc6b423e..8e6adaee6 100644 --- a/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcClientUtils.java +++ b/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcClientUtils.java @@ -39,6 +39,7 @@ public static AbstractOperation preprocessSecurityHook(String uri, Metadata meta SSRFOperation operation = new SSRFOperation(uri, klass, METHOD_NAME_START); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); String iastHeader = NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getRaw(); if (iastHeader != null && !iastHeader.trim().isEmpty()) { diff --git a/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcClientUtils.java b/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcClientUtils.java index 2086ca745..30c9953b7 100644 --- a/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcClientUtils.java +++ b/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcClientUtils.java @@ -39,6 +39,7 @@ public static AbstractOperation preprocessSecurityHook(String uri, Metadata meta SSRFOperation operation = new SSRFOperation(uri, klass, METHOD_NAME_START); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); String iastHeader = NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier().getRaw(); if (iastHeader != null && !iastHeader.trim().isEmpty()) { diff --git a/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/SecurityHelper.java b/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/SecurityHelper.java index fd9727b83..65de23af7 100644 --- a/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/SecurityHelper.java +++ b/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/SecurityHelper.java @@ -52,6 +52,7 @@ public static AbstractOperation preprocessSecurityHook(HttpRequest request, Stri SSRFOperation operation = new SSRFOperation(uri, className, methodName); try { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } finally { if (operation.getApiID() != null && !operation.getApiID().trim().isEmpty() && diff --git a/instrumentation-security/mongodb-3.0/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java b/instrumentation-security/mongodb-3.0/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java index 321b7af27..eb6a3fe42 100644 --- a/instrumentation-security/mongodb-3.0/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java +++ b/instrumentation-security/mongodb-3.0/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java @@ -76,6 +76,7 @@ public static AbstractOperation recordMongoOperation(List command, } } operation = new NoSQLOperation(operations, typeOfOperation, klassName, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(4); NewRelicSecurity.getAgent().registerOperation(operation); } } catch (Throwable e) { @@ -137,6 +138,7 @@ public static AbstractOperation recordWriteRequest(List } } operation = new NoSQLOperation(operations, OP_WRITE, klassName, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(4); NewRelicSecurity.getAgent().registerOperation(operation); } } catch (Throwable e) { diff --git a/instrumentation-security/mongodb-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java b/instrumentation-security/mongodb-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java index 3dfece7fd..24894c897 100644 --- a/instrumentation-security/mongodb-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java +++ b/instrumentation-security/mongodb-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java @@ -88,6 +88,7 @@ public static AbstractOperation recordMongoOperation(List command, } } operation = new NoSQLOperation(operations, typeOfOperation, klassName, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(4); NewRelicSecurity.getAgent().registerOperation(operation); } } catch (Throwable e) { @@ -149,6 +150,7 @@ public static AbstractOperation recordWriteRequest(List } } operation = new NoSQLOperation(operations, OP_WRITE, klassName, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(4); NewRelicSecurity.getAgent().registerOperation(operation); } } catch (Throwable e) { diff --git a/instrumentation-security/mongodb-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java b/instrumentation-security/mongodb-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java index 83f0f7786..672fb2804 100644 --- a/instrumentation-security/mongodb-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java +++ b/instrumentation-security/mongodb-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java @@ -86,6 +86,7 @@ public static AbstractOperation recordMongoOperation(List command, } } operation = new NoSQLOperation(operations, typeOfOperation, klassName, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(4); NewRelicSecurity.getAgent().registerOperation(operation); } } catch (Throwable e) { @@ -147,6 +148,7 @@ public static AbstractOperation recordWriteRequest(List } } operation = new NoSQLOperation(operations, OP_WRITE, klassName, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(4); NewRelicSecurity.getAgent().registerOperation(operation); } } catch (Throwable e) { diff --git a/instrumentation-security/mongodb-3.8/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java b/instrumentation-security/mongodb-3.8/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java index 1f3918270..255c9612f 100644 --- a/instrumentation-security/mongodb-3.8/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java +++ b/instrumentation-security/mongodb-3.8/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java @@ -74,6 +74,7 @@ public static AbstractOperation recordMongoOperation(List command, } } operation = new NoSQLOperation(operations, typeOfOperation, klassName, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(4); NewRelicSecurity.getAgent().registerOperation(operation); } } catch (Throwable e) { @@ -135,6 +136,7 @@ public static AbstractOperation recordWriteRequest(List } } operation = new NoSQLOperation(operations, OP_WRITE, klassName, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(4); NewRelicSecurity.getAgent().registerOperation(operation); } } catch (Throwable e) { diff --git a/instrumentation-security/ning-async-http-client-1.0.0/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_0/NingHelper.java b/instrumentation-security/ning-async-http-client-1.0.0/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_0/NingHelper.java index 4d24a9b23..8711a0146 100644 --- a/instrumentation-security/ning-async-http-client-1.0.0/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_0/NingHelper.java +++ b/instrumentation-security/ning-async-http-client-1.0.0/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_0/NingHelper.java @@ -53,6 +53,7 @@ public static AbstractOperation preprocessSecurityHook(Request request, String u SSRFOperation operation = new SSRFOperation(uri, className, methodName); try { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } finally { if (operation.getApiID() != null && !operation.getApiID().trim().isEmpty() && diff --git a/instrumentation-security/ning-async-http-client-1.1.0/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_1/NingHelper.java b/instrumentation-security/ning-async-http-client-1.1.0/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_1/NingHelper.java index 208c5bd7a..c2d17e323 100644 --- a/instrumentation-security/ning-async-http-client-1.1.0/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_1/NingHelper.java +++ b/instrumentation-security/ning-async-http-client-1.1.0/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_1/NingHelper.java @@ -47,6 +47,7 @@ public static AbstractOperation preprocessSecurityHook(Request request, String u SSRFOperation operation = new SSRFOperation(uri, className, methodName); try { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } finally { if (operation.getApiID() != null && !operation.getApiID().trim().isEmpty() && diff --git a/instrumentation-security/ning-async-http-client-1.6.1/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_6_1/NingHelper.java b/instrumentation-security/ning-async-http-client-1.6.1/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_6_1/NingHelper.java index ad0595b86..c4ecbb2f2 100644 --- a/instrumentation-security/ning-async-http-client-1.6.1/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_6_1/NingHelper.java +++ b/instrumentation-security/ning-async-http-client-1.6.1/src/main/java/com/newrelic/agent/security/instrumentation/ning/http_1_6_1/NingHelper.java @@ -50,6 +50,7 @@ public static AbstractOperation preprocessSecurityHook(Request request, String u SSRFOperation operation = new SSRFOperation(uri, className, methodName); try { + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); } finally { if (operation.getApiID() != null && !operation.getApiID().trim().isEmpty() && diff --git a/instrumentation-security/okhttp-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp30/OkhttpHelper.java b/instrumentation-security/okhttp-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp30/OkhttpHelper.java index ce4ce93ed..21c25c193 100644 --- a/instrumentation-security/okhttp-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp30/OkhttpHelper.java +++ b/instrumentation-security/okhttp-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp30/OkhttpHelper.java @@ -69,6 +69,7 @@ public static AbstractOperation preprocessSecurityHook(String url, String classN SSRFOperation operation = new SSRFOperation(url, className, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(operation); return operation; } catch (Throwable e) { diff --git a/instrumentation-security/okhttp-3.5.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp35/OkhttpHelper.java b/instrumentation-security/okhttp-3.5.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp35/OkhttpHelper.java index 84820a805..ea4ee3192 100644 --- a/instrumentation-security/okhttp-3.5.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp35/OkhttpHelper.java +++ b/instrumentation-security/okhttp-3.5.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp35/OkhttpHelper.java @@ -67,6 +67,7 @@ public static AbstractOperation preprocessSecurityHook(String url, String classN return null; } SSRFOperation ssrfOperation = new SSRFOperation(url, className, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(ssrfOperation); return ssrfOperation; } catch (Throwable e) { diff --git a/instrumentation-security/okhttp-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp40/OkhttpHelper.java b/instrumentation-security/okhttp-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp40/OkhttpHelper.java index 753334036..7f2d936da 100644 --- a/instrumentation-security/okhttp-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp40/OkhttpHelper.java +++ b/instrumentation-security/okhttp-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp40/OkhttpHelper.java @@ -68,6 +68,7 @@ public static AbstractOperation preprocessSecurityHook(String url, String classN return null; } SSRFOperation ssrfOperation = new SSRFOperation(url, className, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(ssrfOperation); return ssrfOperation; } catch (Throwable e) { diff --git a/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java b/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java index 25dcd984a..9c8a58a4a 100644 --- a/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java +++ b/instrumentation-security/spring-webclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/spring/client5/SpringWebClientHelper.java @@ -41,6 +41,7 @@ public static AbstractOperation preprocessSecurityHook(URI url, HttpMethod metho } if (!springClientRequestURIs.contains(url.toString())) { SSRFOperation ssrfOperation = new SSRFOperation(url.toString(), className, methodName); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(ssrfOperation); springClientRequestURIs.add(url.toString()); NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(SPRING_WEB_CLIENT_REQUEST_LIST_CUSTOM_ATTRIB, springClientRequestURIs); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index 3b298e080..8197a103a 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -271,7 +271,7 @@ public void registerOperation(AbstractOperation operation) { operation.setStackTrace(securityMetaData.getMetaData().getServiceTrace()); } else { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - operation.setStackTrace(Arrays.copyOfRange(trace, 2, trace.length)); + operation.setStackTrace(Arrays.copyOfRange(trace, securityMetaData.getMetaData().getFromJumpRequiredInStackTrace(), trace.length)); } // added to fetch request/response in case of grpc requests diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/R2dbcHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/R2dbcHelper.java index b1843ef6f..c23e60285 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/R2dbcHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/R2dbcHelper.java @@ -41,6 +41,7 @@ public static AbstractOperation preprocessSecurityHook(String sql, String method sqlOperation.setPreparedCall(isPrepared); sqlOperation.setParams(params); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3); NewRelicSecurity.getAgent().registerOperation(sqlOperation); return sqlOperation; } catch (Throwable e) { diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java index 2a72ff804..2a94aa67f 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java @@ -35,6 +35,8 @@ public class AgentMetaData { @JsonIgnore private String userLevelServiceMethodEncounteredFramework; + private int fromJumpRequiredInStackTrace = 2; + @JsonIgnore private Set ips; @@ -174,4 +176,12 @@ public AppServerInfo getAppServerInfo() { public void setAppServerInfo(AppServerInfo appServerInfo) { this.appServerInfo = appServerInfo; } + + public int getFromJumpRequiredInStackTrace() { + return fromJumpRequiredInStackTrace; + } + + public void setFromJumpRequiredInStackTrace(int fromJumpRequiredInStackTrace) { + this.fromJumpRequiredInStackTrace = fromJumpRequiredInStackTrace; + } } From bda7ee03cafb58f17ca8bb4e34bb5ca9f9d9b983 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 24 Apr 2024 18:25:50 +0530 Subject: [PATCH 097/124] Add missing fields to AgentMetaData constructor --- .../com/newrelic/api/agent/security/schema/AgentMetaData.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java index 9b333958c..de108e1f4 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java @@ -63,6 +63,9 @@ public AgentMetaData(AgentMetaData agentMetaData) { this.userLevelServiceMethodEncountered = agentMetaData.userLevelServiceMethodEncountered; this.reflectedMetaData = agentMetaData.reflectedMetaData; this.appServerInfo = agentMetaData.appServerInfo; + this.triggerViaXXE = agentMetaData.triggerViaXXE; + this.userLevelServiceMethodEncounteredFramework = agentMetaData.userLevelServiceMethodEncounteredFramework; + this.foundAnnotedUserLevelServiceMethod = agentMetaData.foundAnnotedUserLevelServiceMethod; } public boolean isTriggerViaRCI() { From b70f1ca03e0bf65a7a3d3cd70a6fee748a0cce03 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 29 Apr 2024 12:16:47 +0530 Subject: [PATCH 098/124] Fixed failing UTs --- .../security/instrumentation/tomcat10/APIEndpointTest.java | 5 +---- .../security/instrumentation/tomcat7/APIEndpointTest.java | 5 +---- .../agent/security/instrumentation/jetty11/ServerTest.java | 3 +-- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java index 73c5b14d6..e27acd60a 100644 --- a/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java +++ b/instrumentation-security/apache-tomcat-10/src/test/java/com/nr/agent/security/instrumentation/tomcat10/APIEndpointTest.java @@ -32,9 +32,6 @@ public class APIEndpointTest { public void setupEndpoints() { expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); expectedMappings.put("/index.jsp", null); - expectedMappings.put("/*.jsp", "org.apache.jasper.servlet.JspServlet"); - expectedMappings.put("/", DefaultServlet.class.getName()); - expectedMappings.put("/*.jspx", "org.apache.jasper.servlet.JspServlet"); } @Test @@ -43,7 +40,7 @@ public void testAPIEndpoint() throws Exception { Set mappings = URLMappingsHelper.getApplicationURLMappings(); Assert.assertNotNull(mappings); - Assert.assertEquals(5, mappings.size()); + Assert.assertEquals(2, mappings.size()); for (ApplicationURLMapping mapping : mappings) { assertMappings(mapping); } diff --git a/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java index e382baadf..338994b59 100644 --- a/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java +++ b/instrumentation-security/apache-tomcat-7/src/test/java/com/nr/agent/security/instrumentation/tomcat7/APIEndpointTest.java @@ -32,9 +32,6 @@ public class APIEndpointTest { public void setupEndpoints() { expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); expectedMappings.put("/index.jsp", null); - expectedMappings.put("/*.jsp", "org.apache.jasper.servlet.JspServlet"); - expectedMappings.put("/", DefaultServlet.class.getName()); - expectedMappings.put("/*.jspx", "org.apache.jasper.servlet.JspServlet"); } @Test @@ -43,7 +40,7 @@ public void testAPIEndpoint() throws Exception { Set mappings = URLMappingsHelper.getApplicationURLMappings(); Assert.assertNotNull(mappings); - Assert.assertEquals(5, mappings.size()); + Assert.assertEquals(2, mappings.size()); for (ApplicationURLMapping mapping : mappings) { assertMappings(mapping); } diff --git a/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java b/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java index 78269c9d6..f9087b94f 100644 --- a/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java +++ b/instrumentation-security/jetty-11/src/test/java/com/nr/agent/security/instrumentation/jetty11/ServerTest.java @@ -52,7 +52,6 @@ public class ServerTest { @BeforeClass public static void addMappings() { actualMappings.put("/servlet/*", MyServlet.class.getName()); - actualMappings.put("/", ServletHandler.Default404Servlet.class.getName()); } @After public void teardown() throws Exception { @@ -201,7 +200,7 @@ public void testAPIEndpoint () throws Exception { start(); Set mappings = URLMappingsHelper.getApplicationURLMappings(); - Assert.assertEquals(2, mappings.size()); + Assert.assertEquals(1, mappings.size()); for (ApplicationURLMapping mapping : mappings) { Assert.assertNotNull(mapping); From 729734cb0d23ea76d6a71876acc8cf75743bb6eb Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 29 Apr 2024 13:11:52 +0530 Subject: [PATCH 099/124] Fixed failing UTs --- .../servlet30/ApiEndpointTest.java | 2 +- .../servlet30/HttpServletServer.java | 11 +++++++- .../memcached/test/MemcachedTest.java | 27 ++++++++++--------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java index 9da366969..ee2b16e78 100644 --- a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java +++ b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/ApiEndpointTest.java @@ -20,7 +20,7 @@ public class ApiEndpointTest { @Test public void testURLMappings() { - String handler = DefaultServlet.class.getName(); + String handler = MyServlet.class.getName(); String method = "*"; Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); diff --git a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java index de666f5f6..c577787a3 100644 --- a/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java +++ b/instrumentation-security/servlet-3.0/src/test/java/com/nr/agent/security/instrumentation/servlet30/HttpServletServer.java @@ -13,6 +13,9 @@ import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.net.ServerSocket; @@ -64,7 +67,7 @@ public void onStartup(Set> c, ServletContext ctx){ } }, Collections.emptySet()); - Tomcat.addServlet(context, "servlet", new DefaultServlet()); + Tomcat.addServlet(context, "servlet", new MyServlet()); context.addServletMappingDecoded("/*","servlet"); context.addServletMappingDecoded("/test","servlet"); @@ -88,4 +91,10 @@ private void stop() { } } } +} +class MyServlet extends HttpServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + super.doGet(req, resp); + } } \ No newline at end of file diff --git a/instrumentation-security/spymemcached-2.12.0/src/test/java/com/nr/agent/security/instrumentation/memcached/test/MemcachedTest.java b/instrumentation-security/spymemcached-2.12.0/src/test/java/com/nr/agent/security/instrumentation/memcached/test/MemcachedTest.java index 22f798b3e..2bfb72ddc 100644 --- a/instrumentation-security/spymemcached-2.12.0/src/test/java/com/nr/agent/security/instrumentation/memcached/test/MemcachedTest.java +++ b/instrumentation-security/spymemcached-2.12.0/src/test/java/com/nr/agent/security/instrumentation/memcached/test/MemcachedTest.java @@ -1,6 +1,7 @@ package com.nr.agent.security.instrumentation.memcached.test; import com.github.mwarc.embeddedmemcached.JMemcachedServer; +import com.newrelic.agent.security.instrumentation.spy.memcached.MemcachedHelper; import com.newrelic.agent.security.introspec.InstrumentationTestConfig; import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; import com.newrelic.agent.security.introspec.SecurityIntrospector; @@ -8,6 +9,7 @@ import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.operation.MemcachedOperation; import net.spy.memcached.MemcachedClient; +import net.spy.memcached.ops.StoreType; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -68,7 +70,7 @@ public void testSet() { Assert.assertEquals("No operations detected.", 1, operations.size()); MemcachedOperation operation = (MemcachedOperation) operations.get(0); - verifier(operation, Arrays.asList(key, value), WRITE, "asyncStore"); + verifier(operation, Arrays.asList(key, value), WRITE, "asyncStore", "set"); } @Test @@ -80,7 +82,7 @@ public void testAdd() { Assert.assertEquals("No operations detected.", 1, operations.size()); MemcachedOperation operation = (MemcachedOperation) operations.get(0); - verifier(operation, Arrays.asList(key, value), WRITE, "asyncStore"); + verifier(operation, Arrays.asList(key, value), WRITE, "asyncStore", "add"); } @Test public void testReplace() { @@ -91,7 +93,7 @@ public void testReplace() { Assert.assertEquals("No operations detected.", 1, operations.size()); MemcachedOperation operation = (MemcachedOperation) operations.get(0); - verifier(operation, Arrays.asList(key, value), WRITE, "asyncStore"); + verifier(operation, Arrays.asList(key, value), WRITE, "asyncStore", "replace"); } @Test public void testAppend() { @@ -102,7 +104,7 @@ public void testAppend() { Assert.assertEquals("No operations detected.", 1, operations.size()); MemcachedOperation operation = (MemcachedOperation) operations.get(0); - verifier(operation, Arrays.asList(key, value), UPDATE, "asyncCat"); + verifier(operation, Arrays.asList(key, value), UPDATE, "asyncCat", "append"); } @Test public void testPrepend() { @@ -113,7 +115,7 @@ public void testPrepend() { Assert.assertEquals("No operations detected.", 1, operations.size()); MemcachedOperation operation = (MemcachedOperation) operations.get(0); - verifier(operation, Arrays.asList(key, value), UPDATE, "asyncCat"); + verifier(operation, Arrays.asList(key, value), UPDATE, "asyncCat", "prepend"); } @Test public void testPrepend1() { @@ -124,7 +126,7 @@ public void testPrepend1() { Assert.assertEquals("No operations detected.", 1, operations.size()); MemcachedOperation operation = (MemcachedOperation) operations.get(0); - verifier(operation, Arrays.asList(key, value), UPDATE, "asyncCat"); + verifier(operation, Arrays.asList(key, value), UPDATE, "asyncCat", "prepend"); } @Test public void testCas() { @@ -135,7 +137,7 @@ public void testCas() { Assert.assertEquals("No operations detected.", 1, operations.size()); MemcachedOperation operation = (MemcachedOperation) operations.get(0); - verifier(operation, Arrays.asList(key, value), WRITE, "asyncCAS"); + verifier(operation, Arrays.asList(key, value), WRITE, "asyncCAS", "set"); } @Test public void testCas1() { @@ -146,7 +148,7 @@ public void testCas1() { Assert.assertEquals("No operations detected.", 1, operations.size()); MemcachedOperation operation = (MemcachedOperation) operations.get(0); - verifier(operation, Arrays.asList(key, value), WRITE, "asyncCAS"); + verifier(operation, Arrays.asList(key, value), WRITE, "asyncCAS", "set"); } @Test @@ -158,7 +160,7 @@ public void testAsyncCAS() { Assert.assertEquals("No operations detected.", 1, operations.size()); MemcachedOperation operation = (MemcachedOperation) operations.get(0); - verifier(operation, Arrays.asList(key, value), WRITE, "asyncCAS"); + verifier(operation, Arrays.asList(key, value), WRITE, "asyncCAS", "set"); } @Test public void testAsyncCAS1() { @@ -169,14 +171,15 @@ public void testAsyncCAS1() { Assert.assertEquals("No operations detected.", 1, operations.size()); MemcachedOperation operation = (MemcachedOperation) operations.get(0); - verifier(operation, Arrays.asList(key, value), WRITE, "asyncCAS"); + verifier(operation, Arrays.asList(key, value), WRITE, "asyncCAS", "set"); } - private void verifier(MemcachedOperation operation, List args, String type, String method) { + private void verifier(MemcachedOperation operation, List args, String type, String method, String command) { Assert.assertEquals("Incorrect executed parameters.", args, operation.getArguments()); Assert.assertEquals("Incorrect event case type.", VulnerabilityCaseType.CACHING_DATA_STORE, operation.getCaseType()); Assert.assertEquals("Incorrect event category.", MemcachedOperation.MEMCACHED, operation.getCategory()); - Assert.assertEquals("Incorrect event category.", type, operation.getType()); + Assert.assertEquals("Incorrect event category.", type, operation.getCommand()); + Assert.assertEquals("Incorrect event category.", command, operation.getType()); Assert.assertEquals("Incorrect executed class-name.", memcachedClient.getClass().getName(), operation.getClassName()); Assert.assertEquals("Incorrect executed method-name.", method, operation.getMethodName()); } From 86eb27ebab083b80386482d1a5995e9bbb2bc528 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 30 Apr 2024 16:34:45 +0530 Subject: [PATCH 100/124] CSEC agent home path fallback to AGENT_JAR_LOCATION --- .../newrelic/agent/security/AgentConfig.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java index 244cb4fd3..115eb72f2 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java @@ -29,7 +29,8 @@ public class AgentConfig { public static final String CLEANING_STATUS_SNAPSHOTS_FROM_LOG_DIRECTORY_MAX_S_FILE_COUNT_REACHED_REMOVED_S = "Cleaning status-snapshots from snapshots directory, max %s file count reached removed : %s"; - private static final Object lock = new Object(); + public static final String AGENT_JAR_LOCATION = "agent_jar_location"; + public static final String AGENT_HOME = "agent_home"; private String NR_CSEC_HOME; private String logLevel; @@ -95,20 +96,24 @@ private String applyRequiredLogLevel() { } public boolean setK2HomePath() { - if (NewRelic.getAgent().getConfig().getValue("agent_home") != null) { - NR_CSEC_HOME = NewRelic.getAgent().getConfig().getValue("agent_home"); + String agentJarLocation = NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION); + if (NewRelic.getAgent().getConfig().getValue(AGENT_HOME) != null) { + NR_CSEC_HOME = NewRelic.getAgent().getConfig().getValue(AGENT_HOME); + } else if (StringUtils.isNotBlank(agentJarLocation)){ + //fallback to agent_jar_location as home + NR_CSEC_HOME = agentJarLocation; } else { - NR_CSEC_HOME = "."; + System.err.println("[NR-CSEC-JA] Missing or Incorrect system property `newrelic.home` or environment variable `NEWRELIC_HOME`. Collector exiting."); + return false; } Path k2homePath = Paths.get(NR_CSEC_HOME, IUtilConstants.NR_SECURITY_HOME); CommonUtils.forceMkdirs(k2homePath, DIRECTORY_PERMISSION); NR_CSEC_HOME = k2homePath.toString(); AgentUtils.getInstance().getStatusLogValues().put("csec-home", NR_CSEC_HOME); AgentUtils.getInstance().getStatusLogValues().put("csec-home-permissions", String.valueOf(k2homePath.toFile().canWrite() && k2homePath.toFile().canRead())); - AgentUtils.getInstance().getStatusLogValues().put("agent-location", - NewRelic.getAgent().getConfig().getValue("agent_jar_location")); + AgentUtils.getInstance().getStatusLogValues().put("agent-location", agentJarLocation); if (!isValidK2HomePath(NR_CSEC_HOME)) { - System.err.println("[NR-CSEC-JA] Incomplete startup env parameters provided : Missing or Incorrect NR_CSEC_HOME. Collector exiting."); + System.err.println("[NR-CSEC-JA] Incomplete startup env parameters provided : Missing or Incorrect 'newrelic.home'. Collector exiting."); return false; } return true; From 37ff23d911b8d0025785d7dfa2aad35c39ec1d7f Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 30 Apr 2024 16:44:07 +0530 Subject: [PATCH 101/124] Verify CSEC_HOME creation is successful. --- .../main/java/com/newrelic/agent/security/AgentConfig.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java index 115eb72f2..f2537540b 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java @@ -107,7 +107,10 @@ public boolean setK2HomePath() { return false; } Path k2homePath = Paths.get(NR_CSEC_HOME, IUtilConstants.NR_SECURITY_HOME); - CommonUtils.forceMkdirs(k2homePath, DIRECTORY_PERMISSION); + if(!CommonUtils.forceMkdirs(k2homePath, DIRECTORY_PERMISSION)){ + System.err.println(String.format("[NR-CSEC-JA] CSEC home directory creation failed at %s", NR_CSEC_HOME)); + return false; + } NR_CSEC_HOME = k2homePath.toString(); AgentUtils.getInstance().getStatusLogValues().put("csec-home", NR_CSEC_HOME); AgentUtils.getInstance().getStatusLogValues().put("csec-home-permissions", String.valueOf(k2homePath.toFile().canWrite() && k2homePath.toFile().canRead())); From 54e7380634a8880774d544e1c6789853180ce7c6 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 3 May 2024 10:23:05 +0530 Subject: [PATCH 102/124] add checks to register media type wrt content-type reflected in CC --- .../security/instrumentator/httpclient/RequestUtils.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java index bb66bdbf0..c390f088e 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java @@ -18,6 +18,7 @@ public class RequestUtils { private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); public static final String ERROR_IN_FUZZ_REQUEST_GENERATION = "Error in fuzz request generation {}"; + public static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded"; public static Request generateK2Request(FuzzRequestBean httpRequest, String endpoint) { try { @@ -27,7 +28,7 @@ public static Request generateK2Request(FuzzRequestBean httpRequest, String endp RequestBody requestBody = null; if (StringUtils.isNotBlank(httpRequest.getContentType())) { - if (httpRequest.getParameterMap() != null && !httpRequest.getParameterMap().isEmpty()) { + if (httpRequest.getParameterMap() != null && !httpRequest.getParameterMap().isEmpty() && StringUtils.startsWith(httpRequest.getContentType(), APPLICATION_X_WWW_FORM_URLENCODED)) { FormBody.Builder builder = new FormBody.Builder(); for (Entry param : httpRequest.getParameterMap().entrySet()) { for (int i = 0; i < param.getValue().length; i++) { @@ -35,11 +36,12 @@ public static Request generateK2Request(FuzzRequestBean httpRequest, String endp } } requestBody = builder.build(); - } else { + } else if( StringUtils.isNotBlank(httpRequest.getBody().toString())) { requestBody = RequestBody.create(httpRequest.getBody().toString(), MediaType.parse(httpRequest.getContentType())); } - } else if (StringUtils.equalsIgnoreCase(httpRequest.getMethod(), "POST")) { + } + if (requestBody == null && HttpMethod.permitsRequestBody(httpRequest.getMethod())) { requestBody = RequestBody.create(httpRequest.getBody().toString(), null); } From 2f01f26da70ced9ff3df28ce5403b65a906d9eab Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 10 May 2024 11:25:16 +0530 Subject: [PATCH 103/124] remove sys-out --- .../function/client/ExchangeFunction_Instrumentation.java | 1 - 1 file changed, 1 deletion(-) diff --git a/instrumentation-security/spring-webclient-5.0/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction_Instrumentation.java b/instrumentation-security/spring-webclient-5.0/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction_Instrumentation.java index 1d5f14f99..e773eeb16 100644 --- a/instrumentation-security/spring-webclient-5.0/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction_Instrumentation.java +++ b/instrumentation-security/spring-webclient-5.0/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction_Instrumentation.java @@ -19,7 +19,6 @@ public class ExchangeFunction_Instrumentation { public Mono exchange(ClientRequest request) { - System.out.println("invoked instrumented exchange method"); boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { From ad8439a0f5952f20b5ee41dd2c5d2a83c99e23dd Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Fri, 10 May 2024 11:45:17 +0530 Subject: [PATCH 104/124] [NR-249812] Support For Netty Reactor Server (#220) [FIX] Events generation for Netty Reactor Server Co-authored-by: Lovesh Baya --- .../newrelic/api/agent/security/Agent.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index 9446aff0b..0574af4fa 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -33,7 +33,6 @@ import java.lang.instrument.Instrumentation; import java.lang.instrument.UnmodifiableClassException; import java.net.HttpURLConnection; -import java.net.Socket; import java.net.URL; import java.time.Instant; import java.util.ArrayList; @@ -350,15 +349,30 @@ private void logIfIastScanForFirstTime(K2RequestIdentifier fuzzRequestIdentifier } private static boolean checkIfNRGeneratedEvent(AbstractOperation operation) { + boolean isNettyReactor = false, isNRGeneratedEvent = false; for (int i = 1, j = 0; i < operation.getStackTrace().length; i++) { + if(StringUtils.equalsAny(operation.getStackTrace()[i].getClassName(), "com.nr.instrumentation.TokenLinkingSubscriber", "com.nr.instrumentation.reactor.netty.TokenLinkingSubscriber")){ + isNettyReactor = true; + continue; + } + // Only remove consecutive top com.newrelic and com.nr. elements from stack. if (i - 1 == j && StringUtils.startsWithAny(operation.getStackTrace()[i].getClassName(), "com.newrelic.", "com.nr.")) { j++; } else if (StringUtils.startsWithAny(operation.getStackTrace()[i].getClassName(), "com.newrelic.", "com.nr.")) { - return true; + isNRGeneratedEvent = true; } } - return false; + if (isNettyReactor) { + operation.setStackTrace(removeNettyReactorLinkingTraces(operation.getStackTrace())); + } + return isNRGeneratedEvent; + } + + private static StackTraceElement[] removeNettyReactorLinkingTraces(StackTraceElement[] stackTrace) { + return Arrays.stream(stackTrace).filter(stackTraceElement -> + !StringUtils.equalsAny(stackTraceElement.getClassName(), "com.nr.instrumentation.TokenLinkingSubscriber", "com.nr.instrumentation.reactor.netty.TokenLinkingSubscriber") + ).toArray(StackTraceElement[]::new); } private static boolean needToGenerateEvent(String apiID) { From f4aabf579244065677c0aa58c3e94173e09b1f08 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 10 May 2024 11:45:38 +0530 Subject: [PATCH 105/124] code cleanup --- .../com/newrelic/api/agent/security/schema/AgentMetaData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java index 314c6fa33..8b8487736 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java @@ -188,7 +188,7 @@ public int getFromJumpRequiredInStackTrace() { public void setFromJumpRequiredInStackTrace(int fromJumpRequiredInStackTrace) { this.fromJumpRequiredInStackTrace = fromJumpRequiredInStackTrace; - + } public boolean isFoundAnnotedUserLevelServiceMethod() { return foundAnnotedUserLevelServiceMethod; } From f07a1d11159b37aff22bd271980ee2dbdf25e43b Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 13 May 2024 10:48:09 +0530 Subject: [PATCH 106/124] Fix regression in File Integrity Event generation --- .../instrumentation/helpers/FileHelper.java | 2 ++ .../operation/FileIntegrityOperation.java | 25 +++++++------------ 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/FileHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/FileHelper.java index 2349d6a34..223a44041 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/FileHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/FileHelper.java @@ -141,6 +141,8 @@ public static void checkEntryOfFileIntegrity(List fileNames) { if(NewRelicSecurity.getAgent().getSecurityMetaData().getFileLocalMap().containsKey(fileName)){ FileIntegrityOperation fbean = NewRelicSecurity.getAgent().getSecurityMetaData().getFileLocalMap().get(fileName); if(fbean.isIntegrityBreached(file)){ + //Lock release is required here, as this register operation inside lock is intentional + ThreadLocalLockHelper.releaseLock(); NewRelicSecurity.getAgent().registerOperation(fbean); } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/FileIntegrityOperation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/FileIntegrityOperation.java index d334a4158..cca591220 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/FileIntegrityOperation.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/FileIntegrityOperation.java @@ -144,25 +144,18 @@ public void setPermissionString(String permissionString) { } public boolean isIntegrityBreached(File file){ - boolean lockAcquired = ThreadLocalLockHelper.acquireLock(); try { - if(lockAcquired) { - Boolean exists = file.exists(); - long lastModified = exists ? file.lastModified() : -1; - String permissions = StringUtils.EMPTY; - long length = file.length(); - if (exists) { - PosixFileAttributes fileAttributes = Files.readAttributes(Paths.get(file.getPath()), PosixFileAttributes.class); - Set permissionSet = fileAttributes.permissions(); - permissions = permissionSet.toString(); - } - return (exists != this.exists || lastModified != this.lastModified || !StringUtils.equals(permissions, this.permissionString) || length != this.length); + Boolean exists = file.exists(); + long lastModified = exists ? file.lastModified() : -1; + String permissions = StringUtils.EMPTY; + long length = file.length(); + if (exists) { + PosixFileAttributes fileAttributes = Files.readAttributes(Paths.get(file.getPath()), PosixFileAttributes.class); + Set permissionSet = fileAttributes.permissions(); + permissions = permissionSet.toString(); } + return (exists != this.exists || lastModified != this.lastModified || !StringUtils.equals(permissions, this.permissionString) || length != this.length); } catch (IOException e) { - } finally { - if(lockAcquired) { - ThreadLocalLockHelper.releaseLock(); - } } return false; } From 372bbf228ae7a7018c65ac3fbe8a3e0e45d5f9c5 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 13 May 2024 11:17:27 +0530 Subject: [PATCH 107/124] Refine fuzzing endpoints before replay --- .../httpclient/RequestUtils.java | 28 +++++++++++++++++++ .../instrumentator/httpclient/RestClient.java | 25 ++++++++++++++++- .../httpclient/RestRequestProcessor.java | 3 ++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java index c390f088e..b6a78ba0d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java @@ -10,6 +10,7 @@ import okhttp3.internal.http.HttpMethod; import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -20,6 +21,33 @@ public class RequestUtils { public static final String ERROR_IN_FUZZ_REQUEST_GENERATION = "Error in fuzz request generation {}"; public static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded"; + public static Request generateHeadRequest(FuzzRequestBean httpRequest, String endpoint) { + try { + logger.log(LogLevel.FINEST, String.format("Generate HEAD request : %s", JsonConverter.toJSON(httpRequest.getUrl())), RequestUtils.class.getName()); + StringBuilder url = new StringBuilder(endpoint); + url.append(httpRequest.getUrl()); + Request request = new Request.Builder() + .url(url.toString()) + .head() // Use HEAD to fetch only headers without the body + .build(); + return request; + } catch (Exception e) { + logger.log(LogLevel.FINEST, String.format("Error while Generating HEAD request : %s", JsonConverter.toJSON(httpRequest.getUrl())), RequestUtils.class.getName()); + } + return null; + } + + public static List refineEndpoints(FuzzRequestBean httpRequest, List endpoints) { + List refinedEndpoints = new ArrayList<>(); + for (String endpoint : endpoints) { + Request request = generateHeadRequest(httpRequest, endpoint); + if(RestClient.getInstance().isListening(request)){ + refinedEndpoints.add(endpoint); + } + } + return refinedEndpoints; + } + public static Request generateK2Request(FuzzRequestBean httpRequest, String endpoint) { try { logger.log(LogLevel.FINER, String.format("Firing request : %s", JsonConverter.toJSON(httpRequest)), RequestUtils.class.getName()); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java index f47245526..834c9ee7b 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java @@ -70,7 +70,7 @@ protected OkHttpClient initialValue() { try { ConnectionPool connectionPool = new ConnectionPool(1, 5, TimeUnit.MINUTES); builder = builder.connectionPool(connectionPool); - builder = builder.callTimeout(10, TimeUnit.SECONDS); + builder = builder.callTimeout(5, TimeUnit.SECONDS); // Install the all-trusting trust manager final SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); @@ -159,6 +159,25 @@ public void fireRequest(FuzzRequestBean httpRequest, List endpoints, int } + public boolean isListening(Request request) { + if(request == null){ + return false; + } + + OkHttpClient client = clientThreadLocal.get(); + Call call = client.newCall(request); + try { + Response response = call.execute(); + if(response.isSuccessful()){ + return true; + } + } catch (IOException e) { + logger.log(LogLevel.FINER, String.format("Server is not reachable url: %s", request.url()), RestClient.class.getName()); + return false; + } + return false; + } + public int fireRequest(Request request, int repeatCount, String fuzzRequestId) throws SSLException { OkHttpClient client = clientThreadLocal.get(); @@ -189,6 +208,7 @@ public int fireRequest(Request request, int repeatCount, String fuzzRequestId) t logger.log(LogLevel.FINE, String.format("Request failed due to SSL Exception %s : reason %s", request, e.getMessage()), e, RestClient.class.getName()); throw e; } catch (InterruptedIOException e){ + e.printStackTrace(); if(repeatCount >= 0){ return fireRequest(request, --repeatCount, fuzzRequestId); } @@ -202,6 +222,9 @@ public int fireRequest(Request request, int repeatCount, String fuzzRequestId) t FuzzFailEvent fuzzFailEvent = new FuzzFailEvent(AgentInfo.getInstance().getApplicationUUID()); fuzzFailEvent.setFuzzHeader(request.header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID)); EventSendPool.getInstance().sendEvent(fuzzFailEvent); + } catch (Exception e){ + e.printStackTrace(); + logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, e.getMessage(), request), e, RestClient.class.getName()); } return 999; diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java index fe3cf3f7f..439e31b4c 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java @@ -106,10 +106,13 @@ public Boolean call() throws InterruptedException { } else { boolean postSSL = false; List endpoints = prepareAllEndpoints(NewRelicSecurity.getAgent().getApplicationConnectionConfig()); + logger.log(LogLevel.FINER, String.format("Endpoints to fire : ", endpoints), RestRequestProcessor.class.getSimpleName()); if (endpoints.isEmpty()){ endpoints = prepareAllEndpoints(httpRequest); + logger.log(LogLevel.FINER, String.format("Endpoints to fire in empty: ", endpoints), RestRequestProcessor.class.getSimpleName()); postSSL = true; } + endpoints = RequestUtils.refineEndpoints(httpRequest, endpoints); RestClient.getInstance().fireRequest(httpRequest, endpoints, repeatCount + endpoints.size() -1, controlCommand.getId()); } return true; From 988488a6d20abb968c5221e2fa712d99e00df530 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 13 May 2024 19:16:01 +0530 Subject: [PATCH 108/124] Add fallback to log file creation if, file permissions are not present on log_file_path config --- .../newrelic/agent/security/AgentConfig.java | 24 ++++++++++++++----- .../filelogging/InitLogWriter.java | 22 +++++++++++++---- .../intcodeagent/filelogging/LogWriter.java | 18 +++++++++++--- .../intcodeagent/utils/CommonUtils.java | 8 ++----- 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java index f2537540b..af043606f 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java @@ -17,6 +17,7 @@ import org.apache.commons.lang3.StringUtils; import java.io.File; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -50,7 +51,14 @@ private AgentConfig(){ public void instantiate(){ //Set k2 home path - boolean validHomePath = setK2HomePath(); + try { + boolean validHomePath = setK2HomePath(); + System.out.println("New Relic Security Agent: Setting csec home path to directory:"+NR_CSEC_HOME); + } catch (IOException e) { + String tmpDir = System.getProperty("java.io.tmpdir"); + System.err.println("[NR-CSEC-JA] "+e.getMessage()+" Please find the error in " + tmpDir + File.separator + "NR-CSEC-Logger.err"); + throw new RuntimeException("CSEC Agent Exiting!!! Unable to create csec home directory", e); + } isNRSecurityEnabled = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_ENABLED, false); // Set required Group groupName = applyRequiredGroup(); @@ -95,7 +103,7 @@ private String applyRequiredLogLevel() { return logLevel; } - public boolean setK2HomePath() { + public boolean setK2HomePath() throws IOException { String agentJarLocation = NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION); if (NewRelic.getAgent().getConfig().getValue(AGENT_HOME) != null) { NR_CSEC_HOME = NewRelic.getAgent().getConfig().getValue(AGENT_HOME); @@ -156,7 +164,7 @@ public void setConfig(CollectorConfig config) { this.config = config; } - public void createSnapshotDirectory() { + public void createSnapshotDirectory() throws IOException { Path snapshotDir = Paths.get(osVariables.getSnapshotDir()); // Remove any file with this name from target. if (!snapshotDir.toFile().isDirectory()) { @@ -171,13 +179,17 @@ private void keepMaxStatusLogFiles(int max) { File[] sortedStatusFiles = statusFiles.toArray(new File[0]); Arrays.sort(sortedStatusFiles, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR); FileUtils.deleteQuietly(sortedStatusFiles[0]); - logger.log(LogLevel.INFO, String.format(CLEANING_STATUS_SNAPSHOTS_FROM_LOG_DIRECTORY_MAX_S_FILE_COUNT_REACHED_REMOVED_S, max, sortedStatusFiles[0].getAbsolutePath()), FileLoggerThreadPool.class.getName()); + logger.log(LogLevel.INFO, String.format(CLEANING_STATUS_SNAPSHOTS_FROM_LOG_DIRECTORY_MAX_S_FILE_COUNT_REACHED_REMOVED_S, max, sortedStatusFiles[0].getAbsolutePath()), AgentConfig.class.getName()); } } public void setupSnapshotDir() { - createSnapshotDirectory(); - keepMaxStatusLogFiles(100); + try { + createSnapshotDirectory(); + keepMaxStatusLogFiles(100); + } catch (Exception e) { + logger.log(LogLevel.WARNING, String.format("Snapshot directory creation failed !!! Please check file permissions. error:%s ", e.getMessage()), e, AgentConfig.class.getName()); + } } public String getGroupName() { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/InitLogWriter.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/InitLogWriter.java index 83f8aff4a..ba49ac376 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/InitLogWriter.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/InitLogWriter.java @@ -1,5 +1,6 @@ package com.newrelic.agent.security.intcodeagent.filelogging; +import com.newrelic.agent.security.AgentConfig; import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.os.OSVariables; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; @@ -13,6 +14,7 @@ import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.file.Files; +import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.PosixFilePermissions; import java.text.SimpleDateFormat; @@ -30,6 +32,8 @@ public class InitLogWriter implements Runnable { private static final String STR_COLON = " : "; + public static final String LOGS = "logs"; + public static final String THREAD_NAME_TEMPLATE = " [%s] [%s] "; private static final String LOG_FILE_INITIATED_MSG = "Init Log File initiated.\n"; @@ -74,14 +78,22 @@ public class InitLogWriter implements Runnable { } else { fileName = new File(osVariables.getLogDirectory(), "java-security-collector-init.log").getAbsolutePath(); currentLogFile = new File(fileName); - CommonUtils.forceMkdirs(currentLogFile.getParentFile().toPath(), DIRECTORY_PERMISSION); currentLogFileName = fileName; - createLogFile(); + if(!createLogFile()) { + osVariables.setLogDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), LOGS).toString()); + fileName = new File(osVariables.getLogDirectory(), "java-security-collector-init.log").getAbsolutePath(); + currentLogFile = new File(fileName); + currentLogFileName = fileName; + createLogFile(); + } + } } - private static void createLogFile() { + private static Boolean createLogFile() { try { + CommonUtils.forceMkdirs(currentLogFile.getParentFile().toPath(), DIRECTORY_PERMISSION); + System.out.println("New Relic Security Agent: Writing InitLogs to log file:"+currentLogFile); currentLogFile.setReadable(true, false); writer = new BufferedWriter(new FileWriter(currentLogFileName, true)); writer.write(LOG_FILE_INITIATED_MSG); @@ -95,14 +107,16 @@ private static void createLogFile() { } writer.write(String.format(LOG_CONFIGURED_SUCCESSFULLY_MSG, LogLevel.getLevelName(defaultLogLevel), maxFileSize)); writer.flush(); + return true; } catch (Throwable e) { FileLoggerThreadPool.getInstance().setInitLoggingActive(false); String tmpDir = System.getProperty("java.io.tmpdir"); - System.err.println("[NR-CSEC-JA] Unable to create status log file!!! Please find the error in " + tmpDir + File.separator + "NR-CSEC-Logger.err"); + System.err.println("[NR-CSEC-JA] Init Log : "+e.getMessage()+" Please find the error in " + tmpDir + File.separator + "NR-CSEC-Logger.err"); try { e.printStackTrace(new PrintStream(tmpDir + File.separator + "NR-CSEC-Logger.err")); } catch (FileNotFoundException ex) { } + return false; } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogWriter.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogWriter.java index 5675f8e0f..1fac40082 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogWriter.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogWriter.java @@ -1,5 +1,6 @@ package com.newrelic.agent.security.intcodeagent.filelogging; +import com.newrelic.agent.security.AgentConfig; import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.os.OSVariables; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; @@ -13,6 +14,7 @@ import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.file.Files; +import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.PosixFilePermissions; import java.text.SimpleDateFormat; @@ -28,6 +30,8 @@ public class LogWriter implements Runnable { private static final String STR_COLON = " : "; + public static final String LOGS = "logs"; + public static final String THREAD_NAME_TEMPLATE = " [%s] [%s] "; public static final String CAUSED_BY = "Caused by: "; @@ -64,9 +68,10 @@ public class LogWriter implements Runnable { private String logTime; private static boolean createLogFile() { - CommonUtils.forceMkdirs(currentLogFile.getParentFile().toPath(), IUtilConstants.DIRECTORY_PERMISSION); try { + CommonUtils.forceMkdirs(currentLogFile.getParentFile().toPath(), IUtilConstants.DIRECTORY_PERMISSION); + System.out.println("New Relic Security Agent: Writing to log file:"+currentLogFile); currentLogFile.setReadable(true, false); writer = new BufferedWriter(new FileWriter(currentLogFileName, true)); @@ -81,7 +86,7 @@ private static boolean createLogFile() { FileLoggerThreadPool.getInstance().setLoggingActive(false); } String tmpDir = System.getProperty("java.io.tmpdir"); - System.err.println("[NR-CSEC-JA] Unable to create log file!!! Please find the error in " + tmpDir + File.separator + "NR-CSEC-Logger.err"); + System.err.println("[NR-CSEC-JA] CSEC Log : "+e.getMessage()+" Please find the error in " + tmpDir + File.separator + "NR-CSEC-Logger.err"); try { e.printStackTrace(new PrintStream(tmpDir + File.separator + "NR-CSEC-Logger.err")); } catch (FileNotFoundException ex) { @@ -98,7 +103,14 @@ private static boolean createLogFile() { fileName = new File(osVariables.getLogDirectory(), "java-security-collector.log").getAbsolutePath(); currentLogFile = new File(fileName); currentLogFileName = fileName; - createLogFile(); + if(!createLogFile()) { + osVariables.setLogDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), LOGS).toString()); + fileName = new File(osVariables.getLogDirectory(), "java-security-collector.log").getAbsolutePath(); + currentLogFile = new File(fileName); + currentLogFileName = fileName; + createLogFile(); + } + } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/CommonUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/CommonUtils.java index a3b69b60a..4bc17ee4b 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/CommonUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/CommonUtils.java @@ -24,7 +24,7 @@ public class CommonUtils { public static SecureRandom secureRandom = new SecureRandom(); - public static Boolean forceMkdirs(Path directory, String permissions) { + public static Boolean forceMkdirs(Path directory, String permissions) throws IOException { File existingDirectory = directory.toFile(); Stack pathStack = new Stack<>(); while (!existingDirectory.isDirectory()) { @@ -36,11 +36,7 @@ public static Boolean forceMkdirs(Path directory, String permissions) { existingDirectory = next; } - try { - FileUtils.forceMkdir(directory.toFile()); - } catch (IOException e) { - return false; - } + FileUtils.forceMkdir(directory.toFile()); while (!pathStack.isEmpty()) { try { From 4b4440b50d10918977553210d9c59763c8bb0b7f Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 14 May 2024 10:05:26 +0530 Subject: [PATCH 109/124] Remove exception log on std err --- .../agent/security/instrumentator/httpclient/RestClient.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java index 834c9ee7b..945b1f166 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java @@ -208,7 +208,6 @@ public int fireRequest(Request request, int repeatCount, String fuzzRequestId) t logger.log(LogLevel.FINE, String.format("Request failed due to SSL Exception %s : reason %s", request, e.getMessage()), e, RestClient.class.getName()); throw e; } catch (InterruptedIOException e){ - e.printStackTrace(); if(repeatCount >= 0){ return fireRequest(request, --repeatCount, fuzzRequestId); } @@ -223,7 +222,6 @@ public int fireRequest(Request request, int repeatCount, String fuzzRequestId) t fuzzFailEvent.setFuzzHeader(request.header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID)); EventSendPool.getInstance().sendEvent(fuzzFailEvent); } catch (Exception e){ - e.printStackTrace(); logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, e.getMessage(), request), e, RestClient.class.getName()); } From 769b1f27ee161d8549fae1625dcfbe9f9340e34e Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 14 May 2024 11:57:42 +0530 Subject: [PATCH 110/124] CSEC version bump to 2.0.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c054d02e8..5f4773b20 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # The agent version. -agentVersion=1.2.1 +agentVersion=2.0.0 jsonVersion=1.2.1 # Updated exposed NR APM API version. nrAPIVersion=8.4.0 From 3c8552172c8bc3a735d35544f43f5a36aea59363 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 14 May 2024 13:12:08 +0530 Subject: [PATCH 111/124] Updated Changelogs, README for Release 2.0.0 --- Changelog.md | 27 +++++++++++++++++++++++++++ README.md | 9 +++++++++ 2 files changed, 36 insertions(+) diff --git a/Changelog.md b/Changelog.md index 1cfb63cde..d5221d65a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,33 @@ Noteworthy changes to the agent are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.0] - TBD +### Changes +- [PR-186](https://github.com/newrelic/csec-java-agent/pull/186) Feature to detect API Endpoint of the Application [NR-222163](https://new-relic.atlassian.net/browse/NR-222163) +- [PR-132](https://github.com/newrelic/csec-java-agent/pull/132) JCache Support : The security agent now also supports jCache 1.0.0 and above [NR-175383](https://new-relic.atlassian.net/browse/NR-175383) +- [PR-193](https://github.com/newrelic/csec-java-agent/pull/193) Spray HTTP Server Support : The security agent now also supports Spray HTTP Server version 1.3.1 and above (with scala 2.11 and above) [NR-230246](https://new-relic.atlassian.net/browse/NR-230246), [NR-230248](https://new-relic.atlassian.net/browse/NR-230248) +- [PR-195](https://github.com/newrelic/csec-java-agent/pull/195) Spray Can Server Support : The security agent now also supports Spray Can Server version 1.3.1 and above (with scala 2.11 and above) [NR-230246](https://new-relic.atlassian.net/browse/NR-230246), [NR-230248](https://new-relic.atlassian.net/browse/NR-230248) +- [PR-194](https://github.com/newrelic/csec-java-agent/pull/194) Spray Client Support : The security agent now also supports Spray Client version 1.3.1 and above (with scala 2.11 and above) [NR-230243](https://new-relic.atlassian.net/browse/NR-230243), [NR-230245](https://new-relic.atlassian.net/browse/NR-230245) +- [PR-202](https://github.com/newrelic/csec-java-agent/pull/202) Netty Server support : The security agent now also supports Netty Server version 4.0.0.Final and above. [NR-234864](https://new-relic.atlassian.net/browse/NR-234864) +- [PR-220](https://github.com/newrelic/csec-java-agent/pull/220) Netty Reactor Server support : The security agent now also supports Netty Reactor Server version 0.7.0.RELEASE and above. [NR-249812](https://new-relic.atlassian.net/browse/NR-249812) +- [PR-239](https://github.com/newrelic/csec-java-agent/pull/239) Spring WebClient Support : The security agent now also supports Spring WebClient version 5.0.0.RELEASE and above. [NR-258894](https://new-relic.atlassian.net/browse/NR-258894), [NR-258895](https://new-relic.atlassian.net/browse/NR-258895) +- [PR-112](https://github.com/newrelic/csec-java-agent/pull/112) Spymemcached Support : The security agent now also supports Spymemcached version 2.11 and above. [NR-171576](https://new-relic.atlassian.net/browse/NR-171576) +- Resin Support : The security agent now also supports resin server [NR-171577](https://new-relic.atlassian.net/browse/NR-171577) +- Anorm Support : The security agent now also supports Anorm Datastore version 2.0 to 2.5 [NR-171575](https://new-relic.atlassian.net/browse/NR-171575) + +### Fixes +- [PR-202](https://github.com/newrelic/csec-java-agent/pull/202) Extract Server Configuration to resolve IAST localhost connection with application for Netty server. [NR-238324](https://new-relic.atlassian.net/browse/NR-238324) +- [PR-237](https://github.com/newrelic/csec-java-agent/pull/237) Fix for Correct User Class Detection in Sun-Net-HttpServer [NR-254564](https://new-relic.atlassian.net/browse/NR-254564) +- [PR-243](https://github.com/newrelic/csec-java-agent/pull/243) Improvement in fallback mechanism for NR_CSEC_HOME [NR-260723](https://new-relic.atlassian.net/browse/NR-260723) +- [PR-248](https://github.com/newrelic/csec-java-agent/pull/248) Fix for Regression in File Integrity Event Generation [NR-267172](https://new-relic.atlassian.net/browse/NR-267172) +- [PR-249](https://github.com/newrelic/csec-java-agent/pull/249), [PR-244](https://github.com/newrelic/csec-java-agent/pull/244) Improvements in IAST Replay [NR-267169](https://new-relic.atlassian.net/browse/NR-267169), [NR-265208](https://new-relic.atlassian.net/browse/NR-265208) +- [PR-235](https://github.com/newrelic/csec-java-agent/pull/235) Fix for NullPointerException observed in JDBC-GENERIC [NR-232657](https://new-relic.atlassian.net/browse/NR-232657) +- [PR-226](https://github.com/newrelic/csec-java-agent/pull/226) Fix for NoClassDefFoundError observed in JAVAX-JNDI Instrumentation [NR-254566](https://new-relic.atlassian.net/browse/NR-254566) +- [PR-225](https://github.com/newrelic/csec-java-agent/pull/225) Fix for FileAlreadyExistException observed in IAST Replay [NR-254565](https://new-relic.atlassian.net/browse/NR-254565) +- [PR-222](https://github.com/newrelic/csec-java-agent/pull/222) Exclude Milestone Release for Jax-RS, due to release of version 4.0.0-M2 on 9th March 2024 [NR-256459](https://new-relic.atlassian.net/browse/NR-256459) +- [PR-232](https://github.com/newrelic/csec-java-agent/pull/232) Exclude Latest Release version 12.7.0 for mssql-jdbc released on 08th April 2024 [NR-256461](https://new-relic.atlassian.net/browse/NR-256461) +- [PR-247](https://github.com/newrelic/csec-java-agent/pull/247) Exclude Latest Release version 1.7.14 for Rhino-JS-Engine released on 29th April 2024 [NR-265206](https://new-relic.atlassian.net/browse/NR-265206) + ## [1.2.1] - 2024-4-19 ### Fixes - [NR-259467](https://new-relic.atlassian.net/browse/NR-259467) Fix issue of nested event generation from CSEC's agent itself [PR-230](https://github.com/newrelic/csec-java-agent/pull/230) diff --git a/README.md b/README.md index c1c196271..106f9ba31 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,12 @@ The agent automatically instruments the following frameworks. - Mule ESB 3.6 to 3.9.x - gRPC 1.4.0 to latest** - Jersey 2.0 to latest +- Akka Server 10.0 to latest (with scala 2.11 and above) +- Spray Can 1.3.1 to latest (with scala 2.11 and above) +- Akka HTTP Server 10.0 to latest (with scala 2.11 and above) +- Spray HTTP 1.3.1 to latest (with scala 2.11 and above) +- Netty Server 4.0.0.Final to latest +- Netty Reactor Server 0.7.0.RELEASE to latest ** IAST for **gRPC** requires the dependency [protobuf-java-util](https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java-util) for IAST request replay. @@ -66,6 +72,9 @@ The agent automatically instruments the following HTTP clients and messaging ser - Xalan XPATH 2.1.0 to latest - Async Http Client from 2.0 to latest - Ning Async HTTP Client 1.0.0 to latest +- Akka Client 10.0 to latest (with scala 2.11 and above) +- Spray Can Client 1.3.1 to latest (with scala 2.11 and above) +- Spring WebClient 5.0.0.RELEASE to latest ### Datastores From 8d9b480c705a754b6d055c02448c0e3978b76b75 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 15 May 2024 12:30:23 +0530 Subject: [PATCH 112/124] Schema update for ServerConnectionConfiguration Use head request only to identify connection to endpoint once per configuration --- .../http/scaladsl/server/AkkaCoreUtils.java | 4 ++ .../akka/http/scaladsl/AkkaCoreUtils.java | 4 ++ .../akka/http/scaladsl/AkkaCoreUtils.java | 4 ++ .../akka/http/scaladsl/AkkaCoreUtils.java | 4 ++ .../grpc1400/GrpcServerUtils.java | 8 +-- .../jersey2/HttpRequestHelper.java | 4 ++ .../jersey2/HttpRequestHelper.java | 4 ++ .../jersey2/HttpRequestHelper.java | 4 ++ .../jetty11/HttpServletHelper.java | 8 +-- .../jetty12/server/HttpServletHelper.java | 4 ++ .../jetty9/HttpServletHelper.java | 8 +-- .../io/netty400/utils/NettyUtils.java | 4 ++ .../io/netty400/utils/NettyUtils.java | 4 ++ .../servlet24/HttpServletHelper.java | 3 ++ .../servlet5/HttpServletHelper.java | 3 ++ .../servlet6/HttpServletHelper.java | 3 ++ .../main/scala/spray/can/SprayHttpUtils.java | 4 ++ .../src/main/scala/spray/SprayHttpUtils.java | 4 ++ .../sun/net/httpserver/HttpServerHelper.java | 4 ++ .../httpclient/RequestUtils.java | 22 ++++---- .../httpclient/RestRequestProcessor.java | 25 ++++++--- .../newrelic/api/agent/security/Agent.java | 21 ++++---- .../newrelic/api/agent/security/Agent.java | 5 +- .../api/agent/security/NoOpAgent.java | 5 +- .../api/agent/security/SecurityAgent.java | 5 +- .../helpers/ICsecApiConstants.java | 5 ++ .../agent/security/schema/AppServerInfo.java | 8 +-- .../schema/ServerConnectionConfiguration.java | 54 +++++++++++++++++++ 28 files changed, 183 insertions(+), 52 deletions(-) create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ICsecApiConstants.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ServerConnectionConfiguration.java diff --git a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java index ba4d1ebec..b1a26e7bd 100644 --- a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/AkkaCoreUtils.java @@ -5,6 +5,7 @@ import com.newrelic.api.agent.Token; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -180,6 +181,9 @@ public static void processHttpRequestHeader(HttpRequest request, com.newrelic.ap } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.getHeader(headerKey).get().value()); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = nextHeader.value(); if (headerFullValue != null && !headerFullValue.trim().isEmpty()) { diff --git a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java index 4099208c1..284d64b7a 100644 --- a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java @@ -5,6 +5,7 @@ import com.newrelic.api.agent.Token; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -183,6 +184,9 @@ public static void processHttpRequestHeader(HttpRequest request, com.newrelic.ap } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.getHeader(headerKey).get().value()); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = nextHeader.value(); if (headerFullValue != null && !headerFullValue.trim().isEmpty()) { diff --git a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java index ff826809a..0a0d4fb68 100644 --- a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java @@ -5,6 +5,7 @@ import com.newrelic.api.agent.Token; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -183,6 +184,9 @@ public static void processHttpRequestHeader(HttpRequest request, com.newrelic.ap } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.getHeader(headerKey).get().value()); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = nextHeader.value(); if (headerFullValue != null && !headerFullValue.trim().isEmpty()) { diff --git a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java index 9aa227014..1f3e651c8 100644 --- a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java @@ -6,6 +6,7 @@ import com.newrelic.api.agent.Token; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -193,6 +194,9 @@ public static void processHttpRequestHeader(HttpRequest request, com.newrelic.ap } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.getHeader(headerKey).get().value()); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = nextHeader.value(); if (headerFullValue != null && !headerFullValue.trim().isEmpty()) { diff --git a/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcServerUtils.java b/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcServerUtils.java index b60d767d3..92fe00a3d 100644 --- a/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcServerUtils.java +++ b/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/GrpcServerUtils.java @@ -2,10 +2,7 @@ import com.google.protobuf.Descriptors; import com.newrelic.api.agent.security.NewRelicSecurity; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.GrpcHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.*; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.HttpRequest; import com.newrelic.api.agent.security.schema.SecurityMetaData; @@ -186,6 +183,9 @@ public static void processGRPCRequestMetadata(Metadata metadata, HttpRequest sec NewRelicSecurity.getAgent().getSecurityMetaData().setFuzzRequestIdentifier(ServletHelper.parseFuzzRequestIdentifierHeader(metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER)))); } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(GenericHelper.CSEC_PARENT_ID, metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER))); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; String[] headerElements = metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER)).split(";"); diff --git a/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java b/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java index 3d5b05569..a84a351bc 100644 --- a/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java +++ b/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -151,6 +152,9 @@ public static void processHttpRequestHeader(ContainerRequest request, HttpReques } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, headerFullValue); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } for (String headerValue : header.getValue()) { diff --git a/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java b/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java index 86f4786b3..a52a7a084 100644 --- a/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java +++ b/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -153,6 +154,9 @@ public static void processHttpRequestHeader(ContainerRequest request, HttpReques } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, headerFullValue); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } for (String headerValue : header.getValue()) { diff --git a/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java b/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java index 7bcd414f8..c43db4efe 100644 --- a/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java +++ b/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/HttpRequestHelper.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -151,6 +152,9 @@ public static void processHttpRequestHeader(ContainerRequest request, HttpReques } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, headerFullValue); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } for (String headerValue : header.getValue()) { diff --git a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java index 4f69e8b6c..00c729bec 100644 --- a/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java +++ b/instrumentation-security/jetty-11/src/main/java/com/newrelic/agent/security/instrumentation/jetty11/HttpServletHelper.java @@ -1,10 +1,7 @@ package com.newrelic.agent.security.instrumentation.jetty11; import com.newrelic.api.agent.security.NewRelicSecurity; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.*; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.HttpRequest; @@ -58,6 +55,9 @@ public static void processHttpRequestHeader(HttpServletRequest request, HttpRequ } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.getHeader(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; Enumeration headerElements = request.getHeaders(headerKey); diff --git a/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/HttpServletHelper.java b/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/HttpServletHelper.java index a194d4807..930b540a3 100644 --- a/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/HttpServletHelper.java +++ b/instrumentation-security/jetty-12/src/main/java/com/newrelic/agent/security/instrumentation/jetty12/server/HttpServletHelper.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -57,6 +58,9 @@ public static void processHttpRequestHeader(Request request, HttpRequest securit } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.getHeaders().get(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; diff --git a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java index 24c5b34c1..dd3d81697 100644 --- a/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java +++ b/instrumentation-security/jetty-9/src/main/java/com/newrelic/agent/security/instrumentation/jetty9/HttpServletHelper.java @@ -1,10 +1,7 @@ package com.newrelic.agent.security.instrumentation.jetty9; import com.newrelic.api.agent.security.NewRelicSecurity; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.*; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.HttpRequest; @@ -58,6 +55,9 @@ public static void processHttpRequestHeader(HttpServletRequest request, HttpRequ } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.getHeader(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; diff --git a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java index 7905aa171..3a34eac2e 100644 --- a/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java +++ b/instrumentation-security/netty-4.0.0/src/main/java/security/io/netty400/utils/NettyUtils.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -130,6 +131,9 @@ public static void processHttpRequestHeader(HttpRequest request, com.newrelic.ap } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.headers().get(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; diff --git a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java index 7905aa171..3a34eac2e 100644 --- a/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java +++ b/instrumentation-security/netty-4.0.8/src/main/java/security/io/netty400/utils/NettyUtils.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -130,6 +131,9 @@ public static void processHttpRequestHeader(HttpRequest request, com.newrelic.ap } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.headers().get(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; diff --git a/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java b/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java index 51dadf913..aa6ceacd9 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java +++ b/instrumentation-security/servlet-2.4/src/main/java/com/newrelic/agent/security/instrumentation/servlet24/HttpServletHelper.java @@ -51,6 +51,9 @@ public static void processHttpRequestHeader(HttpServletRequest request, HttpRequ } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.getHeader(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; Enumeration headerElements = request.getHeaders(headerKey); diff --git a/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java b/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java index 3ae9792d9..8c6278daa 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java +++ b/instrumentation-security/servlet-5.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet5/HttpServletHelper.java @@ -50,6 +50,9 @@ public static void processHttpRequestHeader(HttpServletRequest request, HttpRequ } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.getHeader(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; diff --git a/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java b/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java index cd0132143..847d8e440 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java +++ b/instrumentation-security/servlet-6.0/src/main/java/com/newrelic/agent/security/instrumentation/servlet6/HttpServletHelper.java @@ -50,6 +50,9 @@ public static void processHttpRequestHeader(HttpServletRequest request, HttpRequ } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, request.getHeader(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; diff --git a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java index bd9c9f361..c1a134fd7 100644 --- a/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java +++ b/instrumentation-security/spray-can-1.3.1/src/main/scala/spray/can/SprayHttpUtils.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -101,6 +102,9 @@ private static void processHttpRequestHeader(List headers, com.newre } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, headerValue); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } if (takeNextValue) { agentMetaData.setClientDetectedFromXFF(true); diff --git a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java index ceca8c914..0ff49b0ce 100644 --- a/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java +++ b/instrumentation-security/spray-http-1.3.1/src/main/scala/spray/SprayHttpUtils.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -101,6 +102,9 @@ private static void processHttpRequestHeader(List headers, com.newre } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, headerValue); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } if (takeNextValue) { agentMetaData.setClientDetectedFromXFF(true); diff --git a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java index aead82f02..0ee68c2ee 100644 --- a/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java +++ b/instrumentation-security/sun-net-httpserver/src/main/java/com/sun/net/httpserver/HttpServerHelper.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.HttpRequest; @@ -46,6 +47,9 @@ public static void processHttpRequestHeaders(Headers headers, HttpRequest securi } else if(GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, headers.getFirst(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; for (String headerValue : headers.get(headerKey)) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java index ac0b224f8..12e61232f 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java @@ -2,6 +2,7 @@ import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.models.FuzzRequestBean; @@ -10,7 +11,9 @@ import okhttp3.internal.http.HttpMethod; import org.apache.commons.lang3.StringUtils; -import java.util.ArrayList; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -29,6 +32,8 @@ public static Request generateHeadRequest(FuzzRequestBean httpRequest, String en Request request = new Request.Builder() .url(url.toString()) .head() // Use HEAD to fetch only headers without the body + .headers(Headers.of((Map) httpRequest.getHeaders())) + .addHeader(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, "true") .build(); return request; } catch (Exception e) { @@ -37,15 +42,10 @@ public static Request generateHeadRequest(FuzzRequestBean httpRequest, String en return null; } - public static List refineEndpoints(FuzzRequestBean httpRequest, List endpoints) { - List refinedEndpoints = new ArrayList<>(); - for (String endpoint : endpoints) { - Request request = generateHeadRequest(httpRequest, endpoint); - if(RestClient.getInstance().isListening(request)){ - refinedEndpoints.add(endpoint); - } - } - return refinedEndpoints; + + public static boolean refineEndpoints(FuzzRequestBean httpRequest, String endpoint) { + Request request = generateHeadRequest(httpRequest, endpoint); + return RestClient.getInstance().isListening(request); } public static Request generateK2Request(FuzzRequestBean httpRequest, String endpoint) { @@ -121,4 +121,6 @@ public static String extractNRCsecFuzzReqHeader(Headers headers) { } return null; } + + } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java index d42323371..2e87e2ca3 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java @@ -8,6 +8,7 @@ import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.ServerConnectionConfiguration; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.models.FuzzRequestBean; import com.newrelic.agent.security.intcodeagent.models.javaagent.IntCodeControlCommand; @@ -106,14 +107,13 @@ public Boolean call() throws InterruptedException { GrpcClientRequestReplayHelper.getInstance().addToRequestQueue(new ControlCommandDto(controlCommand.getId(), httpRequest, payloadList)); } else { boolean postSSL = false; - List endpoints = prepareAllEndpoints(NewRelicSecurity.getAgent().getApplicationConnectionConfig()); + List endpoints = prepareAllEndpoints(NewRelicSecurity.getAgent().getApplicationConnectionConfig(), httpRequest); logger.log(LogLevel.FINER, String.format("Endpoints to fire : ", endpoints), RestRequestProcessor.class.getSimpleName()); if (endpoints.isEmpty()){ endpoints = prepareAllEndpoints(httpRequest); logger.log(LogLevel.FINER, String.format("Endpoints to fire in empty: ", endpoints), RestRequestProcessor.class.getSimpleName()); postSSL = true; } - endpoints = RequestUtils.refineEndpoints(httpRequest, endpoints); RestClient.getInstance().fireRequest(httpRequest, endpoints, repeatCount + endpoints.size() -1, controlCommand.getId()); } return true; @@ -152,15 +152,28 @@ private List prepareAllEndpoints(FuzzRequestBean httpRequest) { return endpoitns; } - private List prepareAllEndpoints(Map applicationConnectionConfig) { + private List prepareAllEndpoints(Map applicationConnectionConfig, FuzzRequestBean httpRequest) { List endpoitns = new ArrayList<>(); - for (Map.Entry connectionConfig : applicationConnectionConfig.entrySet()) { - endpoitns.add(String.format(ENDPOINT_LOCALHOST_S, connectionConfig.getValue(), connectionConfig.getKey())); - endpoitns.add(String.format(ENDPOINT_LOCALHOST_S, toggleProtocol(connectionConfig.getValue()), connectionConfig.getKey())); + for (Map.Entry connectionConfig : applicationConnectionConfig.entrySet()) { + ServerConnectionConfiguration connectionConfiguration = connectionConfig.getValue(); + if(!connectionConfig.getValue().isConfirmed()){ + if (RequestUtils.refineEndpoints(httpRequest, String.format(ENDPOINT_LOCALHOST_S, connectionConfiguration.getProtocol(), connectionConfiguration.getPort()))) { + updateServerConnectionConfiguration(connectionConfiguration, connectionConfiguration.getProtocol()); + } else if (RequestUtils.refineEndpoints(httpRequest, String.format(ENDPOINT_LOCALHOST_S, toggleProtocol(connectionConfiguration.getProtocol()), connectionConfiguration.getPort()))) { + updateServerConnectionConfiguration(connectionConfiguration, toggleProtocol(connectionConfiguration.getProtocol())); + } + } + endpoitns.add(connectionConfiguration.getEndpoint()); } return endpoitns; } + private void updateServerConnectionConfiguration(ServerConnectionConfiguration connectionConfiguration, String protocol) { + connectionConfiguration.setEndpoint(String.format(ENDPOINT_LOCALHOST_S, protocol, connectionConfiguration.getPort())); + connectionConfiguration.setProtocol(protocol); + connectionConfiguration.setConfirmed(true); + } + private String toggleProtocol(String value) { return StringUtils.equalsAnyIgnoreCase(value, "https")? "http": "https"; } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index d6ae9588c..f40d5602b 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -258,11 +258,15 @@ public void registerOperation(AbstractOperation operation) { securityMetaData.getResponse().setResponseBody( new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_RESPONSE_DATA, List.class)))); } - // end if (operation == null || operation.isEmpty()) { return; } + Boolean csecJavaHeadRequest = securityMetaData.getCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, Boolean.class); + if(csecJavaHeadRequest != null && csecJavaHeadRequest){ + return; + } + String executionId = ExecutionIDGenerator.getExecutionId(); operation.setExecutionId(executionId); operation.setStartTime(Instant.now().toEpochMilli()); @@ -603,18 +607,11 @@ public boolean isLowPriorityInstrumentationEnabled() { public void setApplicationConnectionConfig(int port, String scheme) { AppServerInfo appServerInfo = AppServerInfoHelper.getAppServerInfo(); - appServerInfo.getConnectionConfiguration().put(port, scheme); + ServerConnectionConfiguration serverConnectionConfiguration = new ServerConnectionConfiguration(port, scheme); + appServerInfo.getConnectionConfiguration().put(port, serverConnectionConfiguration); // verifyConnectionAndPut(port, scheme, appServerInfo); } - private void verifyConnectionAndPut(int port, String scheme, AppServerInfo appServerInfo) { - if(isConnectionSuccessful(port, scheme)){ - appServerInfo.getConnectionConfiguration().put(port, scheme); - } else if (isConnectionSuccessful(port,StringUtils.equalsAnyIgnoreCase(scheme, HTTPS_STR)? HTTP_STR : HTTPS_STR)) { - appServerInfo.getConnectionConfiguration().put(port, StringUtils.equalsAnyIgnoreCase(scheme, HTTPS_STR)? HTTP_STR : HTTPS_STR); - } - } - private boolean isConnectionSuccessful(int port, String scheme) { try { java.net.URL endpoint = new URL(String.format("%s://localhost:%s", scheme, port)); @@ -637,13 +634,13 @@ private boolean isConnectionSuccessful(int port, String scheme) { } } - public String getApplicationConnectionConfig(int port) { + public ServerConnectionConfiguration getApplicationConnectionConfig(int port) { AppServerInfo appServerInfo = AppServerInfoHelper.getAppServerInfo(); return appServerInfo.getConnectionConfiguration().get(port); } @Override - public Map getApplicationConnectionConfig() { + public Map getApplicationConnectionConfig() { return AppServerInfoHelper.getAppServerInfo().getConnectionConfiguration(); } diff --git a/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java index 1644b501d..c906210fa 100644 --- a/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -5,6 +5,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.security.schema.ServerConnectionConfiguration; import com.newrelic.api.agent.security.schema.operation.FileIntegrityOperation; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -161,12 +162,12 @@ public void setApplicationConnectionConfig(int port, String scheme) { } @Override - public String getApplicationConnectionConfig(int port) { + public ServerConnectionConfiguration getApplicationConnectionConfig(int port) { return null; } @Override - public Map getApplicationConnectionConfig() { + public Map getApplicationConnectionConfig() { //TODO Ishika please fill this as per your needs return null; } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/NoOpAgent.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/NoOpAgent.java index 055d8f66a..d7ae1ec51 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/NoOpAgent.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/NoOpAgent.java @@ -10,6 +10,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.security.schema.ServerConnectionConfiguration; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -94,12 +95,12 @@ public void setApplicationConnectionConfig(int port, String scheme) { } @Override - public String getApplicationConnectionConfig(int port) { + public ServerConnectionConfiguration getApplicationConnectionConfig(int port) { return null; } @Override - public Map getApplicationConnectionConfig() { + public Map getApplicationConnectionConfig() { return Collections.emptyMap(); } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/SecurityAgent.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/SecurityAgent.java index 1b5be23c0..2ae86ea9e 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/SecurityAgent.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/SecurityAgent.java @@ -9,6 +9,7 @@ import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.security.schema.ServerConnectionConfiguration; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -54,9 +55,9 @@ public interface SecurityAgent { void setApplicationConnectionConfig(int port, String scheme); - String getApplicationConnectionConfig(int port); + ServerConnectionConfiguration getApplicationConnectionConfig(int port); - Map getApplicationConnectionConfig(); + Map getApplicationConnectionConfig(); void log(LogLevel logLevel, String event, Throwable throwableEvent, String logSourceClassName); diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ICsecApiConstants.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ICsecApiConstants.java new file mode 100644 index 000000000..4281ffaec --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ICsecApiConstants.java @@ -0,0 +1,5 @@ +package com.newrelic.api.agent.security.instrumentation.helpers; + +public class ICsecApiConstants { + public static final String NR_CSEC_JAVA_HEAD_REQUEST = "nr-csec-java-head-request"; +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AppServerInfo.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AppServerInfo.java index 53a7b9922..f16dc3588 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AppServerInfo.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AppServerInfo.java @@ -13,7 +13,7 @@ public class AppServerInfo { String applicationTmpDirectory; - Map connectionConfiguration; + Map connectionConfiguration; public AppServerInfo() { connectionConfiguration = new ConcurrentHashMap<>(); @@ -51,11 +51,7 @@ public void setApplicationTmpDirectory(String applicationTmpDirectory) { this.applicationTmpDirectory = applicationTmpDirectory; } - public Map getConnectionConfiguration() { + public Map getConnectionConfiguration() { return connectionConfiguration; } - - public void setConnectionConfiguration(Map connectionConfiguration) { - this.connectionConfiguration = connectionConfiguration; - } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ServerConnectionConfiguration.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ServerConnectionConfiguration.java new file mode 100644 index 000000000..0db051003 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/ServerConnectionConfiguration.java @@ -0,0 +1,54 @@ +package com.newrelic.api.agent.security.schema; + +public class ServerConnectionConfiguration { + + private Integer port; + + private String protocol; + + private boolean confirmed; + + private String endpoint; + + public ServerConnectionConfiguration() { + this.confirmed = false; + } + + public ServerConnectionConfiguration(int port, String scheme) { + this.port = port; + this.protocol = scheme; + this.confirmed = false; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public boolean isConfirmed() { + return confirmed; + } + + public void setConfirmed(boolean confirmed) { + this.confirmed = confirmed; + } + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } +} From 468782749f0ee64eb231ef552c8818f605529430 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 15 May 2024 12:33:37 +0530 Subject: [PATCH 113/124] Change release version to 1.3.0, following https://semver.org/#semantic-versioning-200 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5f4773b20..e0be6fcc8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # The agent version. -agentVersion=2.0.0 +agentVersion=1.3.0 jsonVersion=1.2.1 # Updated exposed NR APM API version. nrAPIVersion=8.4.0 From 8b26550d33059b8995feccca2dedb1ba26095dd5 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 15 May 2024 12:41:33 +0530 Subject: [PATCH 114/124] add NR_CSEC_JAVA_HEAD_REQUEST to security metadata --- .../instrumentation/grpc1220/GrpcServerUtils.java | 8 ++++---- .../security/instrumentation/grpc140/GrpcServerUtils.java | 8 ++++---- .../agent/security/instrumentation/mule36/MuleHelper.java | 4 ++++ .../agent/security/instrumentation/mule37/MuleHelper.java | 4 ++++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcServerUtils.java b/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcServerUtils.java index 9dd55f506..711c0c23d 100644 --- a/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcServerUtils.java +++ b/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/GrpcServerUtils.java @@ -2,10 +2,7 @@ import com.google.protobuf.Descriptors; import com.newrelic.api.agent.security.NewRelicSecurity; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.GrpcHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.*; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.HttpRequest; import com.newrelic.api.agent.security.schema.SecurityMetaData; @@ -188,6 +185,9 @@ public static void processGRPCRequestMetadata(Metadata metadata, HttpRequest sec NewRelicSecurity.getAgent().getSecurityMetaData().setFuzzRequestIdentifier(ServletHelper.parseFuzzRequestIdentifierHeader(metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER)))); } else if (GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(GenericHelper.CSEC_PARENT_ID, metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER))); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; String[] headerElements = metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER)).split(";"); diff --git a/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcServerUtils.java b/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcServerUtils.java index 372aaa012..7e05eb8d5 100644 --- a/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcServerUtils.java +++ b/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/GrpcServerUtils.java @@ -2,10 +2,7 @@ import com.google.protobuf.Descriptors; import com.newrelic.api.agent.security.NewRelicSecurity; -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.GrpcHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; -import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.*; import com.newrelic.api.agent.security.schema.AgentMetaData; import com.newrelic.api.agent.security.schema.HttpRequest; import com.newrelic.api.agent.security.schema.SecurityMetaData; @@ -192,6 +189,9 @@ public static void processGRPCRequestMetadata(Metadata metadata, HttpRequest sec NewRelicSecurity.getAgent().getSecurityMetaData().setFuzzRequestIdentifier(ServletHelper.parseFuzzRequestIdentifierHeader(metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER)))); } else if (GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(GenericHelper.CSEC_PARENT_ID, metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER))); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; String[] headerElements = metadata.get(Metadata.Key.of(headerKey, Metadata.ASCII_STRING_MARSHALLER)).split(";"); diff --git a/instrumentation-security/mule-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mule36/MuleHelper.java b/instrumentation-security/mule-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mule36/MuleHelper.java index c7b8e71b4..3a79f35d7 100644 --- a/instrumentation-security/mule-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mule36/MuleHelper.java +++ b/instrumentation-security/mule-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mule36/MuleHelper.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -57,6 +58,9 @@ public static void processHttpRequestHeader(HttpRequest httpRequest, .getAgent() .getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, httpRequest.getHeaderValue(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; for (String headerValue : httpRequest.getHeaderValues(headerKey)) { diff --git a/instrumentation-security/mule-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mule37/MuleHelper.java b/instrumentation-security/mule-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mule37/MuleHelper.java index 436cb6986..afc9c97ba 100644 --- a/instrumentation-security/mule-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mule37/MuleHelper.java +++ b/instrumentation-security/mule-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mule37/MuleHelper.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.ICsecApiConstants; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.AgentMetaData; @@ -51,6 +52,9 @@ public static void processHttpRequestHeader(HttpRequest httpRequest, com.newreli } else if (GenericHelper.CSEC_PARENT_ID.equals(headerKey)) { NewRelicSecurity.getAgent().getSecurityMetaData() .addCustomAttribute(GenericHelper.CSEC_PARENT_ID, httpRequest.getHeaderValue(headerKey)); + } else if (ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST.equals(headerKey)) { + NewRelicSecurity.getAgent().getSecurityMetaData() + .addCustomAttribute(ICsecApiConstants.NR_CSEC_JAVA_HEAD_REQUEST, true); } String headerFullValue = EMPTY; for (String headerValue : httpRequest.getHeaderValues(headerKey)) { From 75fdc95fea90039c59e290381112fa1c0eebab54 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 15 May 2024 15:10:16 +0530 Subject: [PATCH 115/124] Fix for NPE occurring in AgentMetaData --- .../com/newrelic/api/agent/security/schema/AgentMetaData.java | 1 + 1 file changed, 1 insertion(+) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java index 751f4d24f..015e9ca5a 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/AgentMetaData.java @@ -50,6 +50,7 @@ public AgentMetaData() { public AgentMetaData(AgentMetaData agentMetaData) { this.rciMethodsCalls = new HashSet<>(); + agentMetaData.rciMethodsCalls.remove(null); this.rciMethodsCalls.addAll(agentMetaData.rciMethodsCalls); this.triggerViaDeserialisation = agentMetaData.triggerViaDeserialisation; this.triggerViaRCI = agentMetaData.triggerViaRCI; From e1c004cd7ab965160120be0b9857e4cb3580cd68 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 15 May 2024 17:04:18 +0530 Subject: [PATCH 116/124] Fixed the null entry in case of HEAD request in endpoints list --- .../instrumentator/httpclient/RequestUtils.java | 2 +- .../instrumentator/httpclient/RestClient.java | 4 ++-- .../httpclient/RestRequestProcessor.java | 13 ++++++++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java index 12e61232f..b518f2d63 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java @@ -26,7 +26,7 @@ public class RequestUtils { public static Request generateHeadRequest(FuzzRequestBean httpRequest, String endpoint) { try { - logger.log(LogLevel.FINEST, String.format("Generate HEAD request : %s", JsonConverter.toJSON(httpRequest.getUrl())), RequestUtils.class.getName()); + logger.log(LogLevel.FINEST, String.format("Generate HEAD request : %s%s", endpoint, httpRequest.getUrl()), RequestUtils.class.getName()); StringBuilder url = new StringBuilder(endpoint); url.append(httpRequest.getUrl()); Request request = new Request.Builder() diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java index 2bea81f45..9675891af 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java @@ -170,9 +170,9 @@ public boolean isListening(Request request) { OkHttpClient client = clientThreadLocal.get(); Call call = client.newCall(request); - try { - Response response = call.execute(); + try(Response response = call.execute()) { if(response.isSuccessful()){ + logger.log(LogLevel.FINER, String.format("Server is reachable url: %s", request.url()), RestClient.class.getName()); return true; } } catch (IOException e) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java index 2e87e2ca3..021694b94 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java @@ -108,10 +108,10 @@ public Boolean call() throws InterruptedException { } else { boolean postSSL = false; List endpoints = prepareAllEndpoints(NewRelicSecurity.getAgent().getApplicationConnectionConfig(), httpRequest); - logger.log(LogLevel.FINER, String.format("Endpoints to fire : ", endpoints), RestRequestProcessor.class.getSimpleName()); + logger.log(LogLevel.FINER, String.format("Endpoints to fire : %s", endpoints), RestRequestProcessor.class.getSimpleName()); if (endpoints.isEmpty()){ endpoints = prepareAllEndpoints(httpRequest); - logger.log(LogLevel.FINER, String.format("Endpoints to fire in empty: ", endpoints), RestRequestProcessor.class.getSimpleName()); + logger.log(LogLevel.FINER, String.format("Endpoints to fire in empty: %s", endpoints), RestRequestProcessor.class.getSimpleName()); postSSL = true; } RestClient.getInstance().fireRequest(httpRequest, endpoints, repeatCount + endpoints.size() -1, controlCommand.getId()); @@ -153,19 +153,22 @@ private List prepareAllEndpoints(FuzzRequestBean httpRequest) { } private List prepareAllEndpoints(Map applicationConnectionConfig, FuzzRequestBean httpRequest) { - List endpoitns = new ArrayList<>(); + List endpoints = new ArrayList<>(); for (Map.Entry connectionConfig : applicationConnectionConfig.entrySet()) { ServerConnectionConfiguration connectionConfiguration = connectionConfig.getValue(); if(!connectionConfig.getValue().isConfirmed()){ if (RequestUtils.refineEndpoints(httpRequest, String.format(ENDPOINT_LOCALHOST_S, connectionConfiguration.getProtocol(), connectionConfiguration.getPort()))) { updateServerConnectionConfiguration(connectionConfiguration, connectionConfiguration.getProtocol()); + endpoints.add(connectionConfiguration.getEndpoint()); } else if (RequestUtils.refineEndpoints(httpRequest, String.format(ENDPOINT_LOCALHOST_S, toggleProtocol(connectionConfiguration.getProtocol()), connectionConfiguration.getPort()))) { updateServerConnectionConfiguration(connectionConfiguration, toggleProtocol(connectionConfiguration.getProtocol())); + endpoints.add(connectionConfiguration.getEndpoint()); } + } else { + endpoints.add(connectionConfiguration.getEndpoint()); } - endpoitns.add(connectionConfiguration.getEndpoint()); } - return endpoitns; + return endpoints; } private void updateServerConnectionConfiguration(ServerConnectionConfiguration connectionConfiguration, String protocol) { From 308ff71e3bd2c5aa1eea76584569b0ff338e7061 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 15 May 2024 19:16:47 +0530 Subject: [PATCH 117/124] disabled spymemcache support --- Changelog.md | 1 - settings.gradle | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index d5221d65a..cc3541327 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,7 +14,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-202](https://github.com/newrelic/csec-java-agent/pull/202) Netty Server support : The security agent now also supports Netty Server version 4.0.0.Final and above. [NR-234864](https://new-relic.atlassian.net/browse/NR-234864) - [PR-220](https://github.com/newrelic/csec-java-agent/pull/220) Netty Reactor Server support : The security agent now also supports Netty Reactor Server version 0.7.0.RELEASE and above. [NR-249812](https://new-relic.atlassian.net/browse/NR-249812) - [PR-239](https://github.com/newrelic/csec-java-agent/pull/239) Spring WebClient Support : The security agent now also supports Spring WebClient version 5.0.0.RELEASE and above. [NR-258894](https://new-relic.atlassian.net/browse/NR-258894), [NR-258895](https://new-relic.atlassian.net/browse/NR-258895) -- [PR-112](https://github.com/newrelic/csec-java-agent/pull/112) Spymemcached Support : The security agent now also supports Spymemcached version 2.11 and above. [NR-171576](https://new-relic.atlassian.net/browse/NR-171576) - Resin Support : The security agent now also supports resin server [NR-171577](https://new-relic.atlassian.net/browse/NR-171577) - Anorm Support : The security agent now also supports Anorm Datastore version 2.0 to 2.5 [NR-171575](https://new-relic.atlassian.net/browse/NR-171575) diff --git a/settings.gradle b/settings.gradle index c722fe8bd..8c3bd415a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -158,14 +158,13 @@ include 'instrumentation:jersey-2' include 'instrumentation:jersey-2.16' include 'instrumentation:jersey-3' include 'instrumentation:spring-data-redis' -//include 'instrumentation:jcache-1.0.0' +include 'instrumentation:jcache-1.0.0' include 'instrumentation:lettuce-4.3' include 'instrumentation:lettuce-5.0' -include 'instrumentation:spymemcached-2.12.0' +//include 'instrumentation:spymemcached-2.12.0' include 'instrumentation:jetty-12' include 'instrumentation:mule-3.7' include 'instrumentation:mule-3.6' - include 'instrumentation:websphere-8' include 'instrumentation:grails-1.3' include 'instrumentation:grails-2.0' @@ -191,5 +190,4 @@ include 'instrumentation:servlet-3.0' include 'instrumentation:spray-http-1.3.1' include 'instrumentation:spray-client' include 'instrumentation:spray-can-1.3.1' - include 'instrumentation:spring-webclient-5.0' From c94da8f6898d3174c056a340a47c01e2e3950424 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 16 May 2024 12:27:38 +0530 Subject: [PATCH 118/124] Support for instrumentation of setObject method in prepared statement --- .../PreparedStatement_Instrumentation.java | 137 ++++++++++++++++++ .../instrumentator/dispatcher/Dispatcher.java | 9 ++ .../newrelic/api/agent/security/Agent.java | 3 +- .../schema/operation/SQLOperation.java | 13 +- 4 files changed, 160 insertions(+), 2 deletions(-) diff --git a/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java b/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java index 0690ce8f6..b78888973 100644 --- a/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java +++ b/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java @@ -22,6 +22,8 @@ import com.newrelic.api.agent.weaver.Weaver; import java.math.BigDecimal; +import java.net.URL; +import java.util.Calendar; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; @@ -32,6 +34,9 @@ public abstract class PreparedStatement_Instrumentation { @NewField private Map params; + + @NewField + private Map objectParams; @NewField String preparedSql; @NewField @@ -236,6 +241,128 @@ public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { Weaver.callOriginal(); } + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + setParamValue(parameterIndex, xmlObject.getString()); + Weaver.callOriginal(); + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + setParamValue(parameterIndex, x.toString()); + Weaver.callOriginal(); + } + + public void setURL(int parameterIndex, java.net.URL x) throws SQLException { + setParamValue(parameterIndex, x.toString()); + Weaver.callOriginal(); + } + + public void setArray (int parameterIndex, Array x) throws SQLException { + setObjectParams(parameterIndex, x.getArray()); + Weaver.callOriginal(); + } + public void setDate(int parameterIndex, java.sql.Date x, Calendar cal) throws SQLException { + setParamValue(parameterIndex, x); + Weaver.callOriginal(); + } + public void setTime(int parameterIndex, java.sql.Time x, Calendar cal) throws SQLException { + setParamValue(parameterIndex, x); + Weaver.callOriginal(); + } + public void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal) throws SQLException { + setParamValue(parameterIndex, x); + Weaver.callOriginal(); + } + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + setParamValue(parameterIndex, "null"); + Weaver.callOriginal(); + } + public void setNString(int parameterIndex, String value) throws SQLException { + setParamValue(parameterIndex, value); + Weaver.callOriginal(); + } + + public void setObject(int parameterIndex, Object x) throws SQLException { + if(x instanceof Long || x instanceof Integer || x instanceof Double || + x instanceof Float || x instanceof Boolean || x instanceof Short || + x instanceof String || x instanceof byte[] || x instanceof Timestamp || + x instanceof Date || x instanceof BigDecimal || x instanceof Time) { + setParamValue(parameterIndex, x); + } else if (x instanceof SQLXML) { + setParamValue(parameterIndex, ((SQLXML) x).getString()); + } else if (x instanceof RowId || x instanceof URL) { + setParamValue(parameterIndex, x.toString()); + } else { + //TODO critical-message for inconvertible + setObjectParams(parameterIndex, x); + } + Weaver.callOriginal(); + } + + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { + if(x instanceof Long || x instanceof Integer || x instanceof Double || + x instanceof Float || x instanceof Boolean || x instanceof Short || + x instanceof String || x instanceof byte[] || x instanceof Timestamp || + x instanceof Date || x instanceof BigDecimal || x instanceof Time) { + setParamValue(parameterIndex, x); + } else if (x instanceof SQLXML) { + setParamValue(parameterIndex, ((SQLXML) x).getString()); + } else if (x instanceof RowId || x instanceof URL) { + setParamValue(parameterIndex, x.toString()); + } else { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); + setObjectParams(parameterIndex, x); + } + Weaver.callOriginal(); + } + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { + if(x instanceof Long || x instanceof Integer || x instanceof Double || + x instanceof Float || x instanceof Boolean || x instanceof Short || + x instanceof String || x instanceof byte[] || x instanceof Timestamp || + x instanceof Date || x instanceof BigDecimal || x instanceof Time) { + setParamValue(parameterIndex, x); + } else if (x instanceof SQLXML) { + setParamValue(parameterIndex, ((SQLXML) x).getString()); + } else if (x instanceof RowId || x instanceof URL) { + setParamValue(parameterIndex, x.toString()); + } else { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); + setObjectParams(parameterIndex, x); + } + Weaver.callOriginal(); + } + public void setObject(int parameterIndex, Object x, SQLType targetSqlType) throws SQLException { + if(x instanceof Long || x instanceof Integer || x instanceof Double || + x instanceof Float || x instanceof Boolean || x instanceof Short || + x instanceof String || x instanceof byte[] || x instanceof Timestamp || + x instanceof Date || x instanceof BigDecimal || x instanceof Time) { + setParamValue(parameterIndex, x); + } else if (x instanceof SQLXML) { + setParamValue(parameterIndex, ((SQLXML) x).getString()); + } else if (x instanceof RowId || x instanceof URL) { + setParamValue(parameterIndex, x.toString()); + } else { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); + setObjectParams(parameterIndex, x); + } + Weaver.callOriginal(); + } + public void setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException { + if(x instanceof Long || x instanceof Integer || x instanceof Double || + x instanceof Float || x instanceof Boolean || x instanceof Short || + x instanceof String || x instanceof byte[] || x instanceof Timestamp || + x instanceof Date || x instanceof BigDecimal || x instanceof Time) { + setParamValue(parameterIndex, x); + } else if (x instanceof SQLXML) { + setParamValue(parameterIndex, ((SQLXML) x).getString()); + } else if (x instanceof RowId || x instanceof URL) { + setParamValue(parameterIndex, x.toString()); + } else { + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Instrumentation library: %s , Inconvertible for type : %s", JDBC_GENERIC, x.getClass()), this.getClass().getName()); + setObjectParams(parameterIndex, x); + } + Weaver.callOriginal(); + } + public void clearParameters() throws SQLException { if(params != null){ params.clear(); @@ -260,6 +387,13 @@ private void setParamValue(int index, byte[] value) { params.put(String.valueOf(index), new String(value)); } + private void setObjectParams(int index, Object data) { + if (objectParams == null) { + objectParams = new HashMap<>(); + } + + objectParams.put(String.valueOf(index), data); + } public void addBatch() throws SQLException { boolean isLockAcquired = acquireLockIfPossible(); SQLOperation sqlOperation = null; @@ -269,6 +403,9 @@ public void addBatch() throws SQLException { Map localParams = new HashMap<>(); localParams.putAll(params); sqlOperation.setParams(localParams); + Map localObjParams = new HashMap<>(); + localObjParams.putAll(objectParams); + sqlOperation.setObjectParams(localObjParams); sqlOperation.setDbName(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(JDBCVendor.META_CONST_JDBC_VENDOR, String.class)); sqlOperation.setPreparedCall(true); if(batchSQLOperation==null) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java index a2a04577a..f9755809a 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/Dispatcher.java @@ -510,6 +510,15 @@ private JavaAgentEventBean prepareSQLDbCommandEvent(SQLOperation operation, if(operation.getParams() != null) { query.put(PARAMETERS, new JSONObject(operation.getParams())); } + if(operation.getObjectParams() != null && !operation.getObjectParams().isEmpty()){ + JSONObject jsonObject = (JSONObject) query.get(PARAMETERS); + if(jsonObject == null){ + query.put(PARAMETERS, jsonObject); + } + for (Map.Entry objParameter : operation.getObjectParams().entrySet()) { + jsonObject.put(objParameter.getKey(), JsonConverter.toJSON(objParameter.getValue())); + } + } params.add(query); eventBean.setParameters(params); if (operation.isStoredProcedureCall()) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java index f91a75f86..ffccc8917 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/api/agent/security/Agent.java @@ -413,7 +413,8 @@ private static void processStackTrace(AbstractOperation operation) { AgentMetaData metaData = NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData(); if (stackTrace[i - 1].getLineNumber() > 0 && StringUtils.isNotBlank(stackTrace[i - 1].getFileName()) && - !StringUtils.startsWithAny(stackTrace[i - 1].getClassName(), "com.newrelic.", "com.nr.") + !StringUtils.startsWithAny(stackTrace[i - 1].getClassName(), "com.newrelic.agent.security.", "com.newrelic.api.agent.", + "com.newrelic.agent.deps.", "com.nr.instrumentation.") ) { metaData.setTriggerViaRCI(true); metaData.getRciMethodsCalls() diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java index aab96090d..54d7e807b 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SQLOperation.java @@ -14,6 +14,8 @@ public class SQLOperation extends AbstractOperation { private Map params; + private Map objectParams; + private String dbName = "UNKNOWN"; private boolean isPreparedCall; @@ -24,6 +26,7 @@ public SQLOperation(String className, String methodName) { this.setCaseType(VulnerabilityCaseType.SQL_DB_COMMAND); this.query = EMPTY; this.params = new HashMap<>(); + this.objectParams = new HashMap<>(); } public String getQuery() { @@ -54,7 +57,7 @@ public void setPreparedCall(boolean preparedCall) { public boolean isEmpty() { if (query == null || query.trim().isEmpty()) { return true; - } else if (isPreparedCall) { + } else if (isPreparedCall && params != null) { return query.contains("?") && params.isEmpty(); } return false; @@ -82,6 +85,14 @@ public String getDbName() { return dbName; } + public Map getObjectParams() { + return objectParams; + } + + public void setObjectParams(Map objectParams) { + this.objectParams = objectParams; + } + /** * @param dbName the dbName to set */ From 15b507ab09a12561b4688856b01c25dde334ef15 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 16 May 2024 12:57:08 +0530 Subject: [PATCH 119/124] Update changelog and add the release date --- Changelog.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index cc3541327..9dfaf577d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,7 +4,7 @@ Noteworthy changes to the agent are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.0.0] - TBD +## [1.3.0] - 2024-5-16 ### Changes - [PR-186](https://github.com/newrelic/csec-java-agent/pull/186) Feature to detect API Endpoint of the Application [NR-222163](https://new-relic.atlassian.net/browse/NR-222163) - [PR-132](https://github.com/newrelic/csec-java-agent/pull/132) JCache Support : The security agent now also supports jCache 1.0.0 and above [NR-175383](https://new-relic.atlassian.net/browse/NR-175383) @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-202](https://github.com/newrelic/csec-java-agent/pull/202) Netty Server support : The security agent now also supports Netty Server version 4.0.0.Final and above. [NR-234864](https://new-relic.atlassian.net/browse/NR-234864) - [PR-220](https://github.com/newrelic/csec-java-agent/pull/220) Netty Reactor Server support : The security agent now also supports Netty Reactor Server version 0.7.0.RELEASE and above. [NR-249812](https://new-relic.atlassian.net/browse/NR-249812) - [PR-239](https://github.com/newrelic/csec-java-agent/pull/239) Spring WebClient Support : The security agent now also supports Spring WebClient version 5.0.0.RELEASE and above. [NR-258894](https://new-relic.atlassian.net/browse/NR-258894), [NR-258895](https://new-relic.atlassian.net/browse/NR-258895) +- [PR-219](https://github.com/newrelic/csec-java-agent/pull/219) Enable functionality to scan NewRelic applications using `security.is_home_app` config, default value is false - Resin Support : The security agent now also supports resin server [NR-171577](https://new-relic.atlassian.net/browse/NR-171577) - Anorm Support : The security agent now also supports Anorm Datastore version 2.0 to 2.5 [NR-171575](https://new-relic.atlassian.net/browse/NR-171575) @@ -29,6 +30,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-222](https://github.com/newrelic/csec-java-agent/pull/222) Exclude Milestone Release for Jax-RS, due to release of version 4.0.0-M2 on 9th March 2024 [NR-256459](https://new-relic.atlassian.net/browse/NR-256459) - [PR-232](https://github.com/newrelic/csec-java-agent/pull/232) Exclude Latest Release version 12.7.0 for mssql-jdbc released on 08th April 2024 [NR-256461](https://new-relic.atlassian.net/browse/NR-256461) - [PR-247](https://github.com/newrelic/csec-java-agent/pull/247) Exclude Latest Release version 1.7.14 for Rhino-JS-Engine released on 29th April 2024 [NR-265206](https://new-relic.atlassian.net/browse/NR-265206) +- [PR-219](https://github.com/newrelic/csec-java-agent/pull/219) Fixed an issue where lambda functions were causing class circularity errors [NR-239192](https://new-relic.atlassian.net/browse/NR-239192) +- [PR-219](https://github.com/newrelic/csec-java-agent/pull/219) Resolved a problem where multiple RXSS events were being generated unnecessarily, optimizing the system to only produce a single event as intended. ## [1.2.1] - 2024-4-19 ### Fixes From bb60d419038ba0a8d2f6a7bf4d73b697da378251 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 16 May 2024 21:01:37 +0530 Subject: [PATCH 120/124] Close all the connections from the pool after HEAD firing Co-authored-by: Lovesh Baya --- .../security/instrumentator/httpclient/RestClient.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java index 9675891af..ec44bec82 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java @@ -175,6 +175,9 @@ public boolean isListening(Request request) { logger.log(LogLevel.FINER, String.format("Server is reachable url: %s", request.url()), RestClient.class.getName()); return true; } + if (client.connectionPool() != null) { + client.connectionPool().evictAll(); + } } catch (IOException e) { logger.log(LogLevel.FINER, String.format("Server is not reachable url: %s", request.url()), RestClient.class.getName()); return false; @@ -190,8 +193,7 @@ public int fireRequest(Request request, int repeatCount, String fuzzRequestId) t logger.log(LogLevel.FINER, String.format(FIRING_REQUEST_HEADERS_S, request.headers()), RestClient.class.getName()); Call call = client.newCall(request); - try { - Response response = call.execute(); + try (Response response = call.execute()){ logger.log(LogLevel.FINER, String.format(REQUEST_FIRED_SUCCESS, request), RestClient.class.getName()); if (response.code() >= 500) { logger.postLogMessageIfNecessary(LogLevel.WARNING, From 9d15ee54361ac9e10ff7bc7d7a6047e47b8fd80d Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 16 May 2024 21:05:26 +0530 Subject: [PATCH 121/124] Acquire Thread Lock while performing IAST file creation and deletion --- .../helpers/ServletHelper.java | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java index b43728e93..0a8e7d99d 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/ServletHelper.java @@ -111,24 +111,28 @@ public static K2RequestIdentifier parseFuzzRequestIdentifierHeader(String reques tmpFile = StringUtils.replace(tmpFile, NR_CSEC_VALIDATOR_HOME_TMP, NewRelicSecurity.getAgent().getAgentTempDir()); k2RequestIdentifierInstance.getTempFiles().add(tmpFile); + boolean lockAcquired = ThreadLocalLockHelper.acquireLock(); try { - - File fileToCreate = new File(tmpFile); - if (fileToCreate.getParentFile() != null) { - - File parentFile = fileToCreate; - while(parentFile != null && parentFile.getParentFile() != null && !parentFile.getParentFile().exists()){ - parentFile = parentFile.getParentFile(); + if (lockAcquired) { + File fileToCreate = new File(tmpFile); + if (fileToCreate.getParentFile() != null) { + + File parentFile = fileToCreate; + while (parentFile != null && parentFile.getParentFile() != null && !parentFile.getParentFile().exists()) { + parentFile = parentFile.getParentFile(); + } + filesToRemove.add(parentFile.getAbsolutePath()); + fileToCreate.getParentFile().mkdirs(); + } + if (!fileToCreate.exists()) { + Files.createFile(fileToCreate.toPath()); } - filesToRemove.add(parentFile.getAbsolutePath()); - fileToCreate.getParentFile().mkdirs(); - } - if(!fileToCreate.exists()) { - Files.createFile(fileToCreate.toPath()); } } catch (Throwable e) { String message = "Error while parsing fuzz request : %s"; NewRelicSecurity.getAgent().log(LogLevel.INFO, String.format(message, e.getMessage()), e, ServletHelper.class.getName()); + } finally { + ThreadLocalLockHelper.releaseLock(); } } } @@ -197,12 +201,20 @@ public static Set getFilesToRemove() { } public static void tmpFileCleanUp(List files){ - for (String file : files) { - try { - Files.deleteIfExists(Paths.get(file)); - } catch (IOException e) { + boolean lockAcquired = ThreadLocalLockHelper.acquireLock(); + try { + if (lockAcquired) { + for (String file : files) { + try { + Files.deleteIfExists(Paths.get(file)); + } catch (IOException e) { + } + } } + } finally { + ThreadLocalLockHelper.releaseLock(); } + } public static boolean isResponseContentTypeExcluded( String responseContentType) { From 9005ffd844b2aa8da39a0c9565b0a639220ec8f4 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 16 May 2024 21:29:07 +0530 Subject: [PATCH 122/124] Fix PreparedStatement UTs Co-authored-by: Lovesh Baya --- .../java/java/sql/PreparedStatement_Instrumentation.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java b/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java index b78888973..083fc98da 100644 --- a/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java +++ b/instrumentation-security/jdbc-generic/src/main/java/java/sql/PreparedStatement_Instrumentation.java @@ -401,10 +401,14 @@ public void addBatch() throws SQLException { sqlOperation = new SQLOperation(this.getClass().getName(), JdbcHelper.METHOD_EXECUTE_BATCH); sqlOperation.setQuery(preparedSql); Map localParams = new HashMap<>(); - localParams.putAll(params); + if(params != null) { + localParams.putAll(params); + } sqlOperation.setParams(localParams); Map localObjParams = new HashMap<>(); - localObjParams.putAll(objectParams); + if (objectParams != null) { + localObjParams.putAll(objectParams); + } sqlOperation.setObjectParams(localObjParams); sqlOperation.setDbName(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(JDBCVendor.META_CONST_JDBC_VENDOR, String.class)); sqlOperation.setPreparedCall(true); From 74de0242f8904d0a2c1723dc5d13b0938d9500b3 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 17 May 2024 10:35:04 +0530 Subject: [PATCH 123/124] Update change log remove fix for multiple rxss event generation --- Changelog.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index 9dfaf577d..1cdb97e4f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -30,8 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-222](https://github.com/newrelic/csec-java-agent/pull/222) Exclude Milestone Release for Jax-RS, due to release of version 4.0.0-M2 on 9th March 2024 [NR-256459](https://new-relic.atlassian.net/browse/NR-256459) - [PR-232](https://github.com/newrelic/csec-java-agent/pull/232) Exclude Latest Release version 12.7.0 for mssql-jdbc released on 08th April 2024 [NR-256461](https://new-relic.atlassian.net/browse/NR-256461) - [PR-247](https://github.com/newrelic/csec-java-agent/pull/247) Exclude Latest Release version 1.7.14 for Rhino-JS-Engine released on 29th April 2024 [NR-265206](https://new-relic.atlassian.net/browse/NR-265206) -- [PR-219](https://github.com/newrelic/csec-java-agent/pull/219) Fixed an issue where lambda functions were causing class circularity errors [NR-239192](https://new-relic.atlassian.net/browse/NR-239192) -- [PR-219](https://github.com/newrelic/csec-java-agent/pull/219) Resolved a problem where multiple RXSS events were being generated unnecessarily, optimizing the system to only produce a single event as intended. +- [PR-219](https://github.com/newrelic/csec-java-agent/pull/219) Fixed an issue where lambda functions were causing class circularity errors [NR-239192](https://new-relic.atlassian.net/browse/NR-239192) ## [1.2.1] - 2024-4-19 ### Fixes From a28063226cea5a14d7d0eae347fac8bee3ea8327 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 17 May 2024 10:57:26 +0530 Subject: [PATCH 124/124] Update change log add Revamp user class detection technique --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 1cdb97e4f..c137963d8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-220](https://github.com/newrelic/csec-java-agent/pull/220) Netty Reactor Server support : The security agent now also supports Netty Reactor Server version 0.7.0.RELEASE and above. [NR-249812](https://new-relic.atlassian.net/browse/NR-249812) - [PR-239](https://github.com/newrelic/csec-java-agent/pull/239) Spring WebClient Support : The security agent now also supports Spring WebClient version 5.0.0.RELEASE and above. [NR-258894](https://new-relic.atlassian.net/browse/NR-258894), [NR-258895](https://new-relic.atlassian.net/browse/NR-258895) - [PR-219](https://github.com/newrelic/csec-java-agent/pull/219) Enable functionality to scan NewRelic applications using `security.is_home_app` config, default value is false +- [PR-217](https://github.com/newrelic/csec-java-agent/pull/217) Revamp user class detection technique, use server level endpoints. [NR-211161](https://new-relic.atlassian.net/browse/NR-211161) - Resin Support : The security agent now also supports resin server [NR-171577](https://new-relic.atlassian.net/browse/NR-171577) - Anorm Support : The security agent now also supports Anorm Datastore version 2.0 to 2.5 [NR-171575](https://new-relic.atlassian.net/browse/NR-171575)