From fe60313f0c05a265c3962b4d746096c70b3d9991 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 24 Jan 2025 19:08:49 +0530 Subject: [PATCH 1/2] NR-287770: API Endpoint Support for JSF --- .../apache/tomcat10/HttpServletHelper.java | 20 ++++++++++++------ .../apache/tomcat7/HttpServletHelper.java | 19 +++++++++++------ .../jetty11/HttpServletHelper.java | 20 +++++++++++------- .../jetty9/HttpServletHelper.java | 19 +++++++++++------ .../servlet30/HttpServletHelper.java | 20 +++++++++++------- .../servlet5/HttpServletHelper.java | 21 ++++++++++++------- .../servlet6/HttpServletHelper.java | 21 ++++++++++++------- .../helpers/URLMappingsHelper.java | 10 ++++++--- 8 files changed, 101 insertions(+), 49 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 52f34d54f..06f36d994 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 @@ -21,19 +21,24 @@ public class HttpServletHelper { public static void gatherURLMappings(ServletContext servletContext) { try { Map servletRegistrations = servletContext.getServletRegistrations(); - getJSPMappings(servletContext, SEPARATOR); - + boolean isJSFSupported = false; for (ServletRegistration servletReg : servletRegistrations.values()) { + String handlerName = servletReg.getClassName(); + if (StringUtils.equalsAny(handlerName, URLMappingsHelper.JAVAX_FACES_WEBAPP_FACES_SERVLET, URLMappingsHelper.JAKARTA_FACES_WEBAPP_FACES_SERVLET)) { + isJSFSupported = true; + } for (String mapping : servletReg.getMappings()) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, servletReg.getClassName())); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, handlerName)); } } + getJSPMappings(servletContext, SEPARATOR, isJSFSupported); + } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, APACHE_TOMCAT_10, e.getMessage()), e, HttpServletHelper.class.getName()); } } - private static void getJSPMappings(ServletContext servletContext, String dir) { + private static void getJSPMappings(ServletContext servletContext, String dir, boolean isJSFSupported) { try { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); @@ -43,9 +48,12 @@ private static void getJSPMappings(ServletContext servletContext, String dir) { continue; } if(path.endsWith(SEPARATOR)) { - getJSPMappings(servletContext, path); + getJSPMappings(servletContext, path, isJSFSupported); + } + else if(StringUtils.endsWithAny(path, ".jsp", ".JSP", ".jspx", ".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); } - else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { + else if (isJSFSupported && StringUtils.endsWithAny(path, ".xhtml", ".faces", ".jsf", ".XHTML", ".FACES", ".JSF")) { URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, 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 61bb5ee00..8e4af0b32 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 @@ -20,19 +20,23 @@ public class HttpServletHelper { public static void gatherURLMappings(ServletContext servletContext) { try { Map servletRegistrations = servletContext.getServletRegistrations(); - getJSPMappings(servletContext, SEPARATOR); - + boolean isJSFSupported = false; for (ServletRegistration servletReg : servletRegistrations.values()) { + String handlerName = servletReg.getClassName(); + if (StringUtils.equalsAny(handlerName, URLMappingsHelper.JAVAX_FACES_WEBAPP_FACES_SERVLET, URLMappingsHelper.JAKARTA_FACES_WEBAPP_FACES_SERVLET)) { + isJSFSupported = true; + } for (String mapping : servletReg.getMappings()) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, servletReg.getClassName())); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, handlerName)); } } + getJSPMappings(servletContext, SEPARATOR, isJSFSupported); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, APACHE_TOMCAT_7, e.getMessage()), e, HttpServletHelper.class.getName()); } } - private static void getJSPMappings(ServletContext servletContext, String dir) { + private static void getJSPMappings(ServletContext servletContext, String dir, boolean isJSFSupported) { try { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); @@ -42,9 +46,12 @@ private static void getJSPMappings(ServletContext servletContext, String dir) { continue; } if(path.endsWith(SEPARATOR)) { - getJSPMappings(servletContext, path); + getJSPMappings(servletContext, path, isJSFSupported); + } + else if(StringUtils.endsWithAny(path, ".jsp", ".JSP", ".jspx", ".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); } - else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { + else if (isJSFSupported && StringUtils.endsWithAny(path, ".xhtml", ".faces", ".jsf")) { URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); } } 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 c92ece2ee..f460430f3 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 @@ -183,21 +183,24 @@ public static void postProcessSecurityHook(HttpServletRequest request, HttpServl } public static void gatherURLMappings(ServletContext servletContext) { try { - String contextPath = StringUtils.removeStart(StringUtils.removeEnd(servletContext.getContextPath(), SEPARATOR), StringUtils.SEPARATOR); Map servletRegistrations = servletContext.getServletRegistrations(); - getJSPMappings(servletContext, SEPARATOR); - + boolean isJSFSupported = false; for (ServletRegistration servletReg : servletRegistrations.values()) { + String handlerName = servletReg.getClassName(); + if (StringUtils.equalsAny(handlerName, URLMappingsHelper.JAVAX_FACES_WEBAPP_FACES_SERVLET, URLMappingsHelper.JAKARTA_FACES_WEBAPP_FACES_SERVLET)) { + isJSFSupported = true; + } for (String mapping : servletReg.getMappings()) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, servletReg.getClassName())); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, handlerName)); } } + getJSPMappings(servletContext, SEPARATOR, isJSFSupported); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, JETTY_11, e.getMessage()), e, HttpServletHelper.class.getName()); } } - private static void getJSPMappings(ServletContext servletContext, String dir) { + private static void getJSPMappings(ServletContext servletContext, String dir, boolean isJSFSupported) { try { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); @@ -207,9 +210,12 @@ private static void getJSPMappings(ServletContext servletContext, String dir) { continue; } if(path.endsWith(SEPARATOR)) { - getJSPMappings(servletContext, path); + getJSPMappings(servletContext, path, isJSFSupported); + } + else if(StringUtils.endsWithAny(path, ".jsp", ".JSP", ".jspx", ".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); } - else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { + else if (isJSFSupported && StringUtils.endsWithAny(path, ".xhtml", ".faces", ".jsf", ".XHTML", ".FACES", ".JSF")) { URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); } } 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 a01ba5d19..ad07944bd 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 @@ -186,19 +186,23 @@ public static void postProcessSecurityHook(HttpServletRequest request, HttpServl public static void gatherURLMappings(ServletContext servletContext) { try { Map servletRegistrations = servletContext.getServletRegistrations(); - getJSPMappings(servletContext, SEPARATOR); - + boolean isJSFSupported = false; for (ServletRegistration servletReg : servletRegistrations.values()) { + String handlerName = servletReg.getClassName(); + if (StringUtils.equalsAny(handlerName, URLMappingsHelper.JAVAX_FACES_WEBAPP_FACES_SERVLET, URLMappingsHelper.JAKARTA_FACES_WEBAPP_FACES_SERVLET)) { + isJSFSupported = true; + } for (String mapping : servletReg.getMappings()) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, servletReg.getClassName())); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, handlerName)); } } + getJSPMappings(servletContext, SEPARATOR, isJSFSupported); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, JETTY_9, e.getMessage()), e, HttpServletHelper.class.getName()); } } - private static void getJSPMappings(ServletContext servletContext, String dir) { + private static void getJSPMappings(ServletContext servletContext, String dir, boolean isJSFSupported) { try { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); @@ -208,9 +212,12 @@ private static void getJSPMappings(ServletContext servletContext, String dir) { continue; } if(path.endsWith(SEPARATOR)) { - getJSPMappings(servletContext, path); + getJSPMappings(servletContext, path, isJSFSupported); + } + else if(StringUtils.endsWithAny(path, ".jsp", ".JSP", ".jspx", ".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); } - else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { + else if (isJSFSupported && StringUtils.endsWithAny(path, ".xhtml", ".faces", ".jsf")) { URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); } } 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 fb3039123..9714ea8d7 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 @@ -18,21 +18,24 @@ public class HttpServletHelper { private static final String SERVLET_3_0 = "SERVLET-3.0"; public static void gatherURLMappings(ServletContext servletContext) { try { - String contextPath = StringUtils.removeStart(StringUtils.removeEnd(servletContext.getContextPath(), URLMappingsHelper.SEPARATOR), StringUtils.SEPARATOR); Map servletRegistrations = servletContext.getServletRegistrations(); - getJSPMappings(servletContext, URLMappingsHelper.SEPARATOR); - + boolean isJSFSupported = false; for (ServletRegistration servletReg : servletRegistrations.values()) { + String handlerName = servletReg.getClassName(); + if (StringUtils.equalsAny(handlerName, URLMappingsHelper.JAVAX_FACES_WEBAPP_FACES_SERVLET, URLMappingsHelper.JAKARTA_FACES_WEBAPP_FACES_SERVLET)) { + isJSFSupported = true; + } for (String mapping : servletReg.getMappings()) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, mapping, servletReg.getClassName())); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, mapping, handlerName)); } } + getJSPMappings(servletContext, URLMappingsHelper.SEPARATOR, isJSFSupported); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_3_0, e.getMessage()), e, HttpServletHelper.class.getName()); } } - public static void getJSPMappings(ServletContext servletContext, String dir) { + private static void getJSPMappings(ServletContext servletContext, String dir, boolean isJSFSupported) { try { if(dir.endsWith(URLMappingsHelper.SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); @@ -42,9 +45,12 @@ public static void getJSPMappings(ServletContext servletContext, String dir) { continue; } if(path.endsWith(URLMappingsHelper.SEPARATOR)) { - getJSPMappings(servletContext, path); + getJSPMappings(servletContext, path, isJSFSupported); + } + else if(StringUtils.endsWithAny(path, ".jsp", ".JSP", ".jspx", ".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, path)); } - else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { + else if (isJSFSupported && StringUtils.endsWithAny(path, ".xhtml", ".faces", ".jsf", ".XHTML", ".FACES", ".JSF")) { URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, path)); } } 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 3d2114404..cda87f448 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 @@ -109,19 +109,23 @@ private static String getNrSecCustomAttribName() { public static void gatherURLMappings(ServletContext servletContext) { try { Map servletRegistrations = servletContext.getServletRegistrations(); - getJSPMappings(servletContext, SEPARATOR); - + boolean isJSFSupported = false; for (ServletRegistration servletReg : servletRegistrations.values()) { + String handlerName = servletReg.getClassName(); + if (StringUtils.equalsAny(handlerName, URLMappingsHelper.JAVAX_FACES_WEBAPP_FACES_SERVLET, URLMappingsHelper.JAKARTA_FACES_WEBAPP_FACES_SERVLET)) { + isJSFSupported = true; + } for (String mapping : servletReg.getMappings()) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, servletReg.getClassName())); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, mapping, handlerName)); } } + getJSPMappings(servletContext, URLMappingsHelper.SEPARATOR, isJSFSupported); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_5_0, e.getMessage()), e, HttpServletHelper.class.getName()); } } - public static void getJSPMappings(ServletContext servletContext, String dir) { + public static void getJSPMappings(ServletContext servletContext, String dir, boolean isJSFSupported) { try { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); @@ -131,10 +135,13 @@ public static void getJSPMappings(ServletContext servletContext, String dir) { continue; } if(path.endsWith(SEPARATOR)) { - getJSPMappings(servletContext, path); + getJSPMappings(servletContext, path, isJSFSupported); + } + else if(StringUtils.endsWithAny(path, ".jsp", ".JSP", ".jspx", ".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, path)); } - else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); + else if (isJSFSupported && StringUtils.endsWithAny(path, ".xhtml", ".faces", ".jsf", ".XHTML", ".FACES", ".JSF")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, path)); } } } 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 65c8123b6..f5ec45fd9 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 @@ -118,19 +118,23 @@ private static String getNrSecCustomAttribName() { public static void gatherURLMappings(ServletContext servletContext) { try { Map servletRegistrations = servletContext.getServletRegistrations(); - getJSPMappings(servletContext, SEPARATOR); - + boolean isJSFSupported = false; for (ServletRegistration servletReg : servletRegistrations.values()) { + String handlerName = servletReg.getClassName(); + if (StringUtils.equalsAny(handlerName, URLMappingsHelper.JAVAX_FACES_WEBAPP_FACES_SERVLET, URLMappingsHelper.JAKARTA_FACES_WEBAPP_FACES_SERVLET)) { + isJSFSupported = true; + } for (String mapping : servletReg.getMappings()) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, servletReg.getClassName())); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, mapping, handlerName)); } } + getJSPMappings(servletContext, URLMappingsHelper.SEPARATOR, isJSFSupported); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, SERVLET_6_0, e.getMessage()), e, HttpServletHelper.class.getName()); } } - public static void getJSPMappings(ServletContext servletContext, String dir) { + public static void getJSPMappings(ServletContext servletContext, String dir, boolean isJSFSupported) { try { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); @@ -140,10 +144,13 @@ public static void getJSPMappings(ServletContext servletContext, String dir) { continue; } if(path.endsWith(SEPARATOR)) { - getJSPMappings(servletContext, path); + getJSPMappings(servletContext, path, isJSFSupported); + } + else if(StringUtils.endsWithAny(path, ".jsp", ".JSP", ".jspx", ".JSPX")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, path)); } - else if(path.endsWith(".jsp") || path.endsWith(".jspx") || path.endsWith(".JSP") || path.endsWith(".JSPX")) { - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, path)); + else if (isJSFSupported && StringUtils.endsWithAny(path, ".xhtml", ".faces", ".jsf", ".XHTML", ".FACES", ".JSF")) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, path)); } } } 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 b470c161b..886816e05 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 @@ -22,7 +22,11 @@ public class URLMappingsHelper { public static final String subResourceSegment = "/*"; - private static Set mappings = ConcurrentHashMap.newKeySet(); + public static final String JAVAX_FACES_WEBAPP_FACES_SERVLET = "javax.faces.webapp.FacesServlet"; + + public static final String JAKARTA_FACES_WEBAPP_FACES_SERVLET = "jakarta.faces.webapp.FacesServlet"; + + private static final Set mappings = ConcurrentHashMap.newKeySet(); private static final Set defaultHandlers = new HashSet() {{ add("org.eclipse.jetty.jsp.JettyJspServlet"); @@ -54,9 +58,9 @@ public static Set getApplicationURLMappings() { return mappings; } - private static Set handlers = ConcurrentHashMap.newKeySet(); + private static final Set handlers = ConcurrentHashMap.newKeySet(); - private static Set routeSegments = new TreeSet<>(new RouteComparator()); + private static final Set routeSegments = new TreeSet<>(new RouteComparator()); public static Set getHandlersHash() { return handlers; From 1e562e90fcf83b53b0aca28a592dc00e00cbfbe2 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 12 Mar 2025 21:32:46 +0530 Subject: [PATCH 2/2] Add unit tests for JSF API Endpoint detection --- .../apache-tomcat-10/build.gradle | 1 + .../tomcat10/APIEndpointTest.java | 3 +- .../tomcat10/HttpServletServer.java | 23 ++++++-- .../apache-tomcat-7/build.gradle | 1 + .../tomcat7/APIEndpointTest.java | 6 ++- .../tomcat7/HttpServletServer.java | 16 +++++- .../servlet-3.0/build.gradle | 1 + .../servlet30/ApiEndpointTest.java | 53 ++++++++++--------- .../servlet30/HttpServletServer.java | 41 +++++++++++--- .../servlet-5.0/build.gradle | 1 + .../servlet5/HttpServletServer.java | 41 ++++++++++++-- .../ServletContainerInitializerTest.java | 41 ++++++++++---- .../servlet-6.0/build.gradle | 1 + .../servlet6/HttpServletServer.java | 34 +++++++++++- .../ServletContainerInitializerTest.java | 41 ++++++++++---- 15 files changed, 241 insertions(+), 63 deletions(-) diff --git a/instrumentation-security/apache-tomcat-10/build.gradle b/instrumentation-security/apache-tomcat-10/build.gradle index 337c0de09..ca3baec2f 100644 --- a/instrumentation-security/apache-tomcat-10/build.gradle +++ b/instrumentation-security/apache-tomcat-10/build.gradle @@ -4,6 +4,7 @@ dependencies { 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") + testImplementation("jakarta.faces:jakarta.faces-api:3.0.0") } jar { 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..aeec5e12e 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,7 @@ public class APIEndpointTest { public void setupEndpoints() { expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); expectedMappings.put("/index.jsp", null); + expectedMappings.put("/index.xhtml", null); } @Test @@ -40,7 +41,7 @@ public void testAPIEndpoint() throws Exception { Set mappings = URLMappingsHelper.getApplicationURLMappings(); Assert.assertNotNull(mappings); - Assert.assertEquals(2, mappings.size()); + Assert.assertEquals(3, mappings.size()); for (ApplicationURLMapping mapping : mappings) { assertMappings(mapping); } 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 index dfeac726a..24b4eee30 100644 --- 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 @@ -1,5 +1,10 @@ package com.nr.agent.security.instrumentation.tomcat10; +import jakarta.faces.webapp.FacesServlet; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.catalina.Context; import org.apache.catalina.LifecycleState; import org.apache.catalina.startup.Tomcat; @@ -7,10 +12,6 @@ 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; @@ -65,7 +66,12 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se super.doGet(req, resp); } }); + Tomcat.addServlet(context, "faces", new FacesServlet()); context.setAddWebinfClassesResources(true); + context.addServletMappingDecoded("/faces/*", "faces"); + context.addServletMappingDecoded("*.jsf", "faces"); + context.addServletMappingDecoded("*.faces", "faces"); + context.addServletMappingDecoded("*.xhtml", "faces"); context.addWelcomeFile("/index.jsp"); context.addServletMappingDecoded("/servlet/*","servlet"); @@ -76,14 +82,21 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se public URI getEndPoint(String path) throws URISyntaxException { return new URI("http://localhost:" + port + "/" + path); } + private void createFile() { File indexFile = new File(webappDirLocation + "index.jsp"); + File indexJSFFile = new File(webappDirLocation + "index.xhtml"); try { - if (tmp.mkdir() && indexFile.createNewFile()) { + if (tmp.mkdir() && indexFile.createNewFile() && indexJSFFile.createNewFile()) { BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile)); writer.append("Hello World!"); writer.flush(); writer.close(); + + BufferedWriter writer1 = new BufferedWriter(new FileWriter(indexJSFFile)); + writer1.append("Hello World!"); + writer1.flush(); + writer1.close(); } } catch (IOException e) { throw new RuntimeException(e); diff --git a/instrumentation-security/apache-tomcat-7/build.gradle b/instrumentation-security/apache-tomcat-7/build.gradle index 8614e74a0..4cd1b2e5f 100644 --- a/instrumentation-security/apache-tomcat-7/build.gradle +++ b/instrumentation-security/apache-tomcat-7/build.gradle @@ -4,6 +4,7 @@ dependencies { 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") + testImplementation("javax.faces:jsf-api:2.0") } jar { 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..fa57889d2 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,7 @@ public class APIEndpointTest { public void setupEndpoints() { expectedMappings.put("/servlet/*", HttpServletServer.class.getName()+"$1"); expectedMappings.put("/index.jsp", null); + expectedMappings.put("/index.xhtml", null); } @Test @@ -40,7 +41,7 @@ public void testAPIEndpoint() throws Exception { Set mappings = URLMappingsHelper.getApplicationURLMappings(); Assert.assertNotNull(mappings); - Assert.assertEquals(2, mappings.size()); + Assert.assertEquals(3, mappings.size()); for (ApplicationURLMapping mapping : mappings) { assertMappings(mapping); } @@ -58,9 +59,10 @@ private void assertMappings(ApplicationURLMapping actualMapping) { Assert.assertEquals(handler, actualMapping.getHandler()); Assert.assertEquals("*", actualMapping.getMethod()); } + @Trace(dispatcher = true) private void service() throws IOException, URISyntaxException { - URL u = server.getEndPoint("").toURL(); + URL u = server.getEndPoint("/test").toURL(); HttpURLConnection conn = (HttpURLConnection) u.openConnection(); conn.setRequestProperty("content-type", "text/plain; charset=utf-8"); conn.connect(); 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 index e355d051d..bbbfdefdf 100644 --- 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 @@ -7,6 +7,7 @@ import org.apache.tomcat.util.http.fileupload.FileUtils; import org.junit.rules.ExternalResource; +import javax.faces.webapp.FacesServlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -65,7 +66,12 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se super.doGet(req, resp); } }); + Tomcat.addServlet(context, "faces", new FacesServlet()); context.setAddWebinfClassesResources(true); + context.addServletMapping("/faces/*", "faces"); + context.addServletMapping("*.jsf", "faces"); + context.addServletMapping("*.faces", "faces"); + context.addServletMapping("*.xhtml", "faces"); context.addWelcomeFile("/index.jsp"); context.addServletMapping("/servlet/*","servlet"); @@ -76,19 +82,27 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se public URI getEndPoint(String path) throws URISyntaxException { return new URI("http://localhost:" + port + "/" + path); } + private void createFile() { File indexFile = new File(webappDirLocation + "index.jsp"); + File indexJSFFile = new File(webappDirLocation + "index.xhtml"); try { - if (tmp.mkdir() && indexFile.createNewFile()) { + if (tmp.mkdir() && indexFile.createNewFile() && indexJSFFile.createNewFile()) { BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile)); writer.append("Hello World!"); writer.flush(); writer.close(); + + BufferedWriter writer1 = new BufferedWriter(new FileWriter(indexJSFFile)); + writer1.append("Hello World!"); + writer1.flush(); + writer1.close(); } } catch (IOException e) { throw new RuntimeException(e); } } + private void stop() { if (server.getServer() != null && server.getServer().getState() != LifecycleState.DESTROYED) { try { diff --git a/instrumentation-security/servlet-3.0/build.gradle b/instrumentation-security/servlet-3.0/build.gradle index 1f955ae64..864d91231 100644 --- a/instrumentation-security/servlet-3.0/build.gradle +++ b/instrumentation-security/servlet-3.0/build.gradle @@ -5,6 +5,7 @@ dependencies { implementation('jakarta.servlet:jakarta.servlet-api:4.0.4') testImplementation('org.apache.tomcat.embed:tomcat-embed-core:9.0.70') + testImplementation("javax.faces:jsf-api:2.0") } jar { 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 f7e586c15..340319c95 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 @@ -8,6 +8,7 @@ import com.newrelic.api.agent.security.schema.Framework; import com.newrelic.api.agent.security.schema.SecurityMetaData; import org.junit.Assert; +import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; @@ -16,43 +17,47 @@ import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; +import java.util.HashMap; import java.util.Iterator; +import java.util.Map; +import java.util.Set; @RunWith(SecurityInstrumentationTestRunner.class) @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 = MyServlet.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); + private final Map expectedMappings = new HashMap<>(); - Assert.assertTrue("URL Mappings", mappings.hasNext()); - ApplicationURLMapping mapping2 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); + @Before + public void setupEndpoints() { + expectedMappings.put("/servlet/*", MyServlet.class.getName()); + expectedMappings.put("/index.jsp", null); + expectedMappings.put("/index.xhtml", null); } @Test - public void testRoute() throws IOException, URISyntaxException { - connect(); - SecurityMetaData metaData = SecurityInstrumentationTestRunner.getIntrospector().getSecurityMetaData(); - Assert.assertEquals( "Incorrect Route Detected","/test", metaData.getRequest().getRoute()); - Assert.assertEquals("Incorrect Framework detected", Framework.SERVLET.name(), metaData.getMetaData().getFramework()); + public void testURLMappings() { + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertNotNull(mappings); + Assert.assertEquals(3, mappings.size()); + for (ApplicationURLMapping mapping : mappings) { + assertMappings(mapping); + } } - @Trace(dispatcher = true) - private void connect() 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(); + 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.assertEquals(handler, actualMapping.getHandler()); + Assert.assertEquals("*", actualMapping.getMethod()); } } 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 5a137d4b3..881872d32 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 @@ -8,6 +8,7 @@ import org.apache.tomcat.util.http.fileupload.FileUtils; import org.junit.rules.ExternalResource; +import javax.faces.webapp.FacesServlet; import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; import javax.servlet.ServletException; @@ -15,7 +16,9 @@ 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; @@ -28,7 +31,8 @@ public class HttpServletServer extends ExternalResource { private final int port; private Tomcat server; - private File tmp; + private final String webappDirLocation = "./src/test/webapp/"; + private final File tmp = new File(webappDirLocation); public HttpServletServer() { this.port = getRandomPort(); } @@ -53,14 +57,15 @@ private static int getRandomPort() { private void startServer () throws Exception { TomcatURLStreamHandlerFactory.disable(); + createFile(); server = new Tomcat(); server.setPort(port); - tmp = new File("./tmp"); - server.setBaseDir(tmp.getAbsolutePath()); + server.setBaseDir(webappDirLocation); + server.addWebapp("", tmp.getAbsolutePath()); - Context context = server.addContext("", tmp.getAbsolutePath()); + Context context = server.addContext("/tmp", tmp.getAbsolutePath()); context.addServletContainerInitializer(new ServletContainerInitializer() { @Override public void onStartup(Set> c, ServletContext ctx){ @@ -69,8 +74,12 @@ public void onStartup(Set> c, ServletContext ctx){ }, Collections.emptySet()); Tomcat.addServlet(context, "servlet", new MyServlet()); - context.addServletMappingDecoded("/*","servlet"); - context.addServletMappingDecoded("/test","servlet"); + Tomcat.addServlet(context, "faces", new FacesServlet()); + context.setAddWebinfClassesResources(true); + context.addServletMappingDecoded("/faces/*", "faces"); + context.addServletMappingDecoded("*.xhtml", "faces"); + context.addWelcomeFile("/index.jsp"); + context.addServletMappingDecoded("/servlet/*","servlet"); final Connector connector = new Connector(); connector.setPort(port); @@ -79,6 +88,26 @@ public void onStartup(Set> c, ServletContext ctx){ server.start(); } + private void createFile() { + File indexFile = new File(webappDirLocation + "index.jsp"); + File indexJSFFile = new File(webappDirLocation + "index.xhtml"); + try { + if (tmp.mkdir() && indexFile.createNewFile() && indexJSFFile.createNewFile()) { + BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile)); + writer.append("Hello World!"); + writer.flush(); + writer.close(); + + BufferedWriter writer1 = new BufferedWriter(new FileWriter(indexJSFFile)); + writer1.append("Hello World!"); + writer1.flush(); + writer1.close(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + private void stop() { if (server.getServer() != null && server.getServer().getState() != LifecycleState.DESTROYED) { try { diff --git a/instrumentation-security/servlet-5.0/build.gradle b/instrumentation-security/servlet-5.0/build.gradle index 7e2917077..8b4a14588 100644 --- a/instrumentation-security/servlet-5.0/build.gradle +++ b/instrumentation-security/servlet-5.0/build.gradle @@ -5,6 +5,7 @@ dependencies { implementation('jakarta.servlet:jakarta.servlet-api:5.0.0') testImplementation('org.apache.tomcat.embed:tomcat-embed-core:10.0.27') + testImplementation("jakarta.faces:jakarta.faces-api:3.0.0") } jar { 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 e45ae3c5d..4b69a28fb 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,18 +1,22 @@ package com.nr.agent.security.instrumentation.servlet5; +import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner; +import jakarta.faces.webapp.FacesServlet; 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; -import org.apache.catalina.connector.Connector; 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.junit.rules.ExternalResource; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.net.ServerSocket; import java.net.URI; @@ -25,7 +29,8 @@ public class HttpServletServer extends ExternalResource { private final int port; private Tomcat server; - private File tmp; + private final String webappDirLocation = "./src/test/webapp/"; + private File tmp = new File(webappDirLocation); public HttpServletServer() { this.port = getRandomPort(); } @@ -60,10 +65,11 @@ private void startServer () throws Exception { 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) throws ServletException { @@ -71,9 +77,16 @@ public void onStartup(Set> c, ServletContext ctx) throws ServletExcepti } }, Collections.emptySet()); + createFile(); + Tomcat.addServlet( context, "servlet" , servlet); + Tomcat.addServlet(context, "faces", new FacesServlet()); context.addServletMappingDecoded("/*","servlet"); context.addServletMappingDecoded("/test","servlet"); + context.addServletMappingDecoded("/faces/*", "faces"); + context.addServletMappingDecoded("*.xhtml", "faces"); + + context.addWelcomeFile("/index.jsp"); final Connector connector = new Connector(); connector.setPort(port); @@ -100,4 +113,24 @@ private void stop() { } tmp = null; } + + private void createFile() { + File indexFile = new File(webappDirLocation + "index.jsp"); + File indexJSFFile = new File(webappDirLocation + "index.xhtml"); + try { + if ((tmp.exists() || tmp.mkdir()) && indexFile.createNewFile() && indexJSFFile.createNewFile()) { + BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile)); + writer.append("Hello World!"); + writer.flush(); + writer.close(); + + BufferedWriter writer1 = new BufferedWriter(new FileWriter(indexJSFFile)); + writer1.append("Hello World!"); + writer1.flush(); + writer1.close(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } } \ 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..02f2887e4 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 @@ -5,30 +5,53 @@ import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import org.junit.Assert; +import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.HashMap; import java.util.Iterator; +import java.util.Map; +import java.util.Set; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "jakarta.servlet", "com.newrelic.agent.security.instrumentation.servlet5" }) public class ServletContainerInitializerTest { + @ClassRule public static HttpServletServer server = new HttpServletServer(); + private final Map expectedMappings = new HashMap<>(); + + @Before + public void setupEndpoints() { + expectedMappings.put("/*", "com.nr.agent.security.instrumentation.servlet5.HttpTestServlet"); + expectedMappings.put("/test", "com.nr.agent.security.instrumentation.servlet5.HttpTestServlet"); + expectedMappings.put("/index.jsp", null); + expectedMappings.put("/index.xhtml", null); + } + @Test public void testURLMappings() { - String handler = "com.nr.agent.security.instrumentation.servlet5.HttpTestServlet"; - String method = "*"; - Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertNotNull(mappings); + Assert.assertEquals(4, 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.assertTrue("URL Mappings", mappings.hasNext()); - ApplicationURLMapping mapping1 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); + Assert.assertNotNull(actualMapping.getMethod()); - Assert.assertTrue("URL Mappings", mappings.hasNext()); - ApplicationURLMapping mapping2 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); + Assert.assertEquals(handler, actualMapping.getHandler()); + Assert.assertEquals("*", actualMapping.getMethod()); } } diff --git a/instrumentation-security/servlet-6.0/build.gradle b/instrumentation-security/servlet-6.0/build.gradle index f669df706..24b618e1a 100644 --- a/instrumentation-security/servlet-6.0/build.gradle +++ b/instrumentation-security/servlet-6.0/build.gradle @@ -5,6 +5,7 @@ dependencies { implementation('jakarta.servlet:jakarta.servlet-api:6.0.0') testImplementation('org.apache.tomcat.embed:tomcat-embed-core:10.0.27') + testImplementation("jakarta.faces:jakarta.faces-api:3.0.0") } jar { 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 f725baa32..abfeb0882 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,6 @@ package com.nr.agent.security.instrumentation.servlet6; +import jakarta.faces.webapp.FacesServlet; import jakarta.servlet.ServletContainerInitializer; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; @@ -13,7 +14,9 @@ import org.apache.tomcat.util.http.fileupload.FileUtils; import org.junit.rules.ExternalResource; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.net.ServerSocket; import java.net.URI; @@ -26,7 +29,8 @@ public class HttpServletServer extends ExternalResource { private final int port; private Tomcat server; - private File tmp; + private final String webappDirLocation = "./src/test/webapp/"; + private File tmp = new File(webappDirLocation); public HttpServletServer() { this.port = getRandomPort(); } @@ -60,7 +64,6 @@ private void startServer () throws Exception { server = new Tomcat(); server.setPort(port); - tmp = new File("./tmp"); server.setBaseDir(tmp.getAbsolutePath()); Context context = server.addContext("", tmp.getAbsolutePath()); @@ -71,9 +74,16 @@ public void onStartup(Set> c, ServletContext ctx) throws ServletExcepti } }, Collections.emptySet()); + createFile(); + Tomcat.addServlet( context, "servlet" , servlet); + Tomcat.addServlet(context, "faces", new FacesServlet()); context.addServletMappingDecoded("/*","servlet"); context.addServletMappingDecoded("/test","servlet"); + context.addServletMappingDecoded("/faces/*", "faces"); + context.addServletMappingDecoded("*.xhtml", "faces"); + + context.addWelcomeFile("/index.jsp"); final Connector connector = new Connector(); connector.setPort(port); @@ -101,4 +111,24 @@ private void stop() { } tmp = null; } + + private void createFile() { + File indexFile = new File(webappDirLocation + "index.jsp"); + File indexJSFFile = new File(webappDirLocation + "index.xhtml"); + try { + if ((tmp.exists() || tmp.mkdir()) && indexFile.createNewFile() && indexJSFFile.createNewFile()) { + BufferedWriter writer = new BufferedWriter(new FileWriter(indexFile)); + writer.append("Hello World!"); + writer.flush(); + writer.close(); + + BufferedWriter writer1 = new BufferedWriter(new FileWriter(indexJSFFile)); + writer1.append("Hello World!"); + writer1.flush(); + writer1.close(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } } \ No newline at end of file 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..e57f3d82a 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 @@ -5,30 +5,53 @@ import com.newrelic.api.agent.security.instrumentation.helpers.URLMappingsHelper; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import org.junit.Assert; +import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.HashMap; import java.util.Iterator; +import java.util.Map; +import java.util.Set; @RunWith(SecurityInstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = { "jakarta.servlet", "com.newrelic.agent.security.instrumentation.servlet6" }) public class ServletContainerInitializerTest { + @ClassRule public static HttpServletServer server = new HttpServletServer(); + private final Map expectedMappings = new HashMap<>(); + + @Before + public void setupEndpoints() { + expectedMappings.put("/*", "com.nr.agent.security.instrumentation.servlet6.HttpTestServlet"); + expectedMappings.put("/test", "com.nr.agent.security.instrumentation.servlet6.HttpTestServlet"); + expectedMappings.put("/index.jsp", null); + expectedMappings.put("/index.xhtml", null); + } + @Test public void testURLMappings() { - String handler = "com.nr.agent.security.instrumentation.servlet6.HttpTestServlet"; - String method = "*"; - Iterator mappings = URLMappingsHelper.getApplicationURLMappings().iterator(); + Set mappings = URLMappingsHelper.getApplicationURLMappings(); + Assert.assertNotNull(mappings); + Assert.assertEquals(4, 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.assertTrue("URL Mappings", mappings.hasNext()); - ApplicationURLMapping mapping1 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/*", handler), mapping1); + Assert.assertNotNull(actualMapping.getMethod()); - Assert.assertTrue("URL Mappings", mappings.hasNext()); - ApplicationURLMapping mapping2 = mappings.next(); - Assert.assertEquals("URL Mappings", new ApplicationURLMapping(method, "/test", handler), mapping2); + Assert.assertEquals(handler, actualMapping.getHandler()); + Assert.assertEquals("*", actualMapping.getMethod()); } }