Skip to content

Commit

Permalink
NR-313390: Route detection support for Apache Struts2 Framework
Browse files Browse the repository at this point in the history
  • Loading branch information
IshikaDawda committed Sep 25, 2024
1 parent 1b7651c commit 149bbc2
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 5 deletions.
2 changes: 1 addition & 1 deletion instrumentation-security/apache-struts2/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ dependencies {
implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}")
implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}")
implementation('org.apache.struts:struts2-core:6.1.2')
implementation("javax.servlet:javax.servlet-api:4.0.1")
}

jar {
manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.apache-struts2' }
}

verifyInstrumentation {
passesOnly 'org.apache.struts.xwork:xwork-core:[0,)'
passesOnly 'org.apache.struts:struts2-core:[2.1.2,)'
excludeRegex 'org.apache.struts:struts2-core:2.3.15.1-atlassian-[4-5]$'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,49 @@
import com.newrelic.api.agent.security.NewRelicSecurity;
import com.newrelic.api.agent.security.schema.ApplicationURLMapping;
import com.newrelic.api.agent.security.instrumentation.helpers.*;
import com.newrelic.api.agent.security.schema.Framework;
import com.newrelic.api.agent.security.schema.StringUtils;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.RuntimeConfiguration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import org.apache.struts2.dispatcher.mapper.ActionMapping;

import java.util.Map;

public class StrutsHelper {

private static final String SEPARATOR = "/";
private static final String WILDCARD = "*";
private static final String APACHE_STRUTS2 = "APACHE-STRUTS2";

public static void gatherURLMappings(RuntimeConfiguration runtimeConfig) {
try {
Map<String, Map<String, ActionConfig>> namespaces = runtimeConfig.getActionConfigs();
for (Map.Entry<String, Map<String, ActionConfig>> namespace : namespaces.entrySet()) {
String url = namespace.getKey();
for (ActionConfig actionConfig : namespace.getValue().values()) {
String mapping = StringUtils.appendIfMissing(url, SEPARATOR) + actionConfig.getName();
URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, mapping, actionConfig.getClassName()));
String mapping = StringUtils.appendIfMissing(url, URLMappingsHelper.SEPARATOR) + actionConfig.getName();
URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, mapping, actionConfig.getClassName()));
}
}
} catch (Exception ignored){
NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, APACHE_STRUTS2, ignored.getMessage()), ignored, StrutsHelper.class.getName());
}
}

public static void setRoute(ActionMapping mapping, ConfigurationManager configManager) {
if (!NewRelicSecurity.isHookProcessingActive()){
return;
}
try {
if (mapping != null && mapping.getNamespace() != null && configManager.getConfiguration() != null && configManager.getConfiguration().getRuntimeConfiguration() != null){
ActionConfig actionConfig = configManager.getConfiguration().getRuntimeConfiguration().getActionConfig(mapping.getNamespace(), mapping.getName());
if (actionConfig != null){
NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(StringUtils.appendIfMissing(mapping.getNamespace(), URLMappingsHelper.SEPARATOR) + actionConfig.getName());
NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.APACHE_STRUTS2);
}
}
} catch (Exception ignored){
NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, APACHE_STRUTS2, ignored.getMessage()), ignored, StrutsHelper.class.getName());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.apache.struts2.dispatcher.mapper;

import com.newrelic.agent.security.instrumentation.apache.struts2.StrutsHelper;
import com.newrelic.api.agent.weaver.MatchType;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.opensymphony.xwork2.config.ConfigurationManager;

import javax.servlet.http.HttpServletRequest;

@Weave(originalName = "org.apache.struts2.dispatcher.mapper.ActionMapper", type = MatchType.Interface)
public class DefaultActionMapper_Instrumentation {

public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
ActionMapping mapping = Weaver.callOriginal();
StrutsHelper.setRoute(mapping, configManager);
return mapping;
}
}

0 comments on commit 149bbc2

Please sign in to comment.