From 8d61c7366d33147214dafb4059c63dba8a59b437 Mon Sep 17 00:00:00 2001 From: Monu Lakshkar Date: Sat, 27 Jan 2024 12:41:59 +0530 Subject: [PATCH 001/122] gRPC: API endpoint detection for v1.4.0+ --- .../grpc/BindableService_Instrumentation.java | 24 +++++++++++++++++++ .../grpc/BindableService_Instrumentation.java | 24 +++++++++++++++++++ .../grpc/BindableService_Instrumentation.java | 24 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/BindableService_Instrumentation.java create mode 100644 instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/BindableService_Instrumentation.java create mode 100644 instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/BindableService_Instrumentation.java diff --git a/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/BindableService_Instrumentation.java b/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/BindableService_Instrumentation.java new file mode 100644 index 000000000..b813e5293 --- /dev/null +++ b/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/BindableService_Instrumentation.java @@ -0,0 +1,24 @@ +package io.grpc; + +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; + +@Weave(originalName = "io.grpc.BindableService", type = MatchType.Interface) +public class BindableService_Instrumentation { + public ServerServiceDefinition bindService() { + ServerServiceDefinition returnValue = Weaver.callOriginal(); + + String handler = this.getClass().getName(); + for (ServerMethodDefinition serverMethod : returnValue.getMethods()) { + MethodDescriptor methodDescriptor = serverMethod.getMethodDescriptor(); + String url = methodDescriptor.getFullMethodName(); + String methodType = methodDescriptor.getType().name(); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler)); + } + + return returnValue; + } +} diff --git a/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/BindableService_Instrumentation.java b/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/BindableService_Instrumentation.java new file mode 100644 index 000000000..b813e5293 --- /dev/null +++ b/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/BindableService_Instrumentation.java @@ -0,0 +1,24 @@ +package io.grpc; + +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; + +@Weave(originalName = "io.grpc.BindableService", type = MatchType.Interface) +public class BindableService_Instrumentation { + public ServerServiceDefinition bindService() { + ServerServiceDefinition returnValue = Weaver.callOriginal(); + + String handler = this.getClass().getName(); + for (ServerMethodDefinition serverMethod : returnValue.getMethods()) { + MethodDescriptor methodDescriptor = serverMethod.getMethodDescriptor(); + String url = methodDescriptor.getFullMethodName(); + String methodType = methodDescriptor.getType().name(); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler)); + } + + return returnValue; + } +} diff --git a/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/BindableService_Instrumentation.java b/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/BindableService_Instrumentation.java new file mode 100644 index 000000000..b813e5293 --- /dev/null +++ b/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/BindableService_Instrumentation.java @@ -0,0 +1,24 @@ +package io.grpc; + +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; + +@Weave(originalName = "io.grpc.BindableService", type = MatchType.Interface) +public class BindableService_Instrumentation { + public ServerServiceDefinition bindService() { + ServerServiceDefinition returnValue = Weaver.callOriginal(); + + String handler = this.getClass().getName(); + for (ServerMethodDefinition serverMethod : returnValue.getMethods()) { + MethodDescriptor methodDescriptor = serverMethod.getMethodDescriptor(); + String url = methodDescriptor.getFullMethodName(); + String methodType = methodDescriptor.getType().name(); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler)); + } + + return returnValue; + } +} From b1eee479e06a8da1a16ea6e3ab2396723b7111ce Mon Sep 17 00:00:00 2001 From: Monu Lakshkar Date: Sat, 27 Jan 2024 16:09:37 +0530 Subject: [PATCH 002/122] gRPC: added critical logging --- .../grpc/BindableService_Instrumentation.java | 20 +++++++++++++------ .../grpc/BindableService_Instrumentation.java | 20 +++++++++++++------ .../grpc/BindableService_Instrumentation.java | 20 +++++++++++++------ 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/BindableService_Instrumentation.java b/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/BindableService_Instrumentation.java index b813e5293..2b4be8dd3 100644 --- a/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/BindableService_Instrumentation.java +++ b/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/BindableService_Instrumentation.java @@ -1,7 +1,10 @@ package io.grpc; +import com.newrelic.agent.security.instrumentation.grpc1220.GrpcUtils; +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 com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -11,12 +14,17 @@ public class BindableService_Instrumentation { public ServerServiceDefinition bindService() { ServerServiceDefinition returnValue = Weaver.callOriginal(); - String handler = this.getClass().getName(); - for (ServerMethodDefinition serverMethod : returnValue.getMethods()) { - MethodDescriptor methodDescriptor = serverMethod.getMethodDescriptor(); - String url = methodDescriptor.getFullMethodName(); - String methodType = methodDescriptor.getType().name(); - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler)); + try { + String handler = this.getClass().getName(); + for (ServerMethodDefinition serverMethod : returnValue.getMethods()) { + MethodDescriptor methodDescriptor = serverMethod.getMethodDescriptor(); + String url = methodDescriptor.getFullMethodName(); + String methodType = methodDescriptor.getType().name(); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler)); + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, GrpcUtils.GRPC_1_22_0, e.getMessage()), e, this.getClass().getName()); } return returnValue; diff --git a/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/BindableService_Instrumentation.java b/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/BindableService_Instrumentation.java index b813e5293..edeafd068 100644 --- a/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/BindableService_Instrumentation.java +++ b/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/BindableService_Instrumentation.java @@ -1,7 +1,10 @@ package io.grpc; +import com.newrelic.agent.security.instrumentation.grpc140.GrpcUtils; +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 com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -11,12 +14,17 @@ public class BindableService_Instrumentation { public ServerServiceDefinition bindService() { ServerServiceDefinition returnValue = Weaver.callOriginal(); - String handler = this.getClass().getName(); - for (ServerMethodDefinition serverMethod : returnValue.getMethods()) { - MethodDescriptor methodDescriptor = serverMethod.getMethodDescriptor(); - String url = methodDescriptor.getFullMethodName(); - String methodType = methodDescriptor.getType().name(); - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler)); + try { + String handler = this.getClass().getName(); + for (ServerMethodDefinition serverMethod : returnValue.getMethods()) { + MethodDescriptor methodDescriptor = serverMethod.getMethodDescriptor(); + String url = methodDescriptor.getFullMethodName(); + String methodType = methodDescriptor.getType().name(); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler)); + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, GrpcUtils.GRPC_1_4_0, e.getMessage()), e, this.getClass().getName()); } return returnValue; diff --git a/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/BindableService_Instrumentation.java b/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/BindableService_Instrumentation.java index b813e5293..c1cb1f4e5 100644 --- a/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/BindableService_Instrumentation.java +++ b/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/BindableService_Instrumentation.java @@ -1,7 +1,10 @@ package io.grpc; +import com.newrelic.agent.security.instrumentation.grpc1400.GrpcUtils; +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 com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -11,12 +14,17 @@ public class BindableService_Instrumentation { public ServerServiceDefinition bindService() { ServerServiceDefinition returnValue = Weaver.callOriginal(); - String handler = this.getClass().getName(); - for (ServerMethodDefinition serverMethod : returnValue.getMethods()) { - MethodDescriptor methodDescriptor = serverMethod.getMethodDescriptor(); - String url = methodDescriptor.getFullMethodName(); - String methodType = methodDescriptor.getType().name(); - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler)); + try { + String handler = this.getClass().getName(); + for (ServerMethodDefinition serverMethod : returnValue.getMethods()) { + MethodDescriptor methodDescriptor = serverMethod.getMethodDescriptor(); + String url = methodDescriptor.getFullMethodName(); + String methodType = methodDescriptor.getType().name(); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(methodType, url, handler)); + } + } catch (Exception e){ + String message = "Instrumentation library: %s , error while getting app endpoints : %s"; + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(message, GrpcUtils.GRPC_1_40_0, e.getMessage()), e, this.getClass().getName()); } return returnValue; From 8682d81f9304c85275e27b178c9aa2ea90334604 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 22 May 2024 13:53:42 +0530 Subject: [PATCH 003/122] Boilerplate and pojo changes for JA SA metric data posting --- gradle.properties | 2 +- .../instrumentator/dispatcher/Dispatcher.java | 1 + .../dispatcher/DispatcherPool.java | 98 +++---- .../httpclient/EventAbortPolicy.java | 2 + .../httpclient/RestRequestThreadPool.java | 1 + .../ControlCommandProcessor.java | 3 + .../ControlCommandProcessorThreadPool.java | 4 + .../filelogging/FileLoggerThreadPool.java | 4 + .../filelogging/LogFileHelper.java | 2 + .../logging/HealthCheckScheduleThread.java | 21 +- .../models/javaagent/AgentBasicInfo.java | 10 + .../models/javaagent/DroppedEvents.java | 94 ++++++ .../models/javaagent/EventMetric.java | 70 +++++ .../models/javaagent/EventStats.java | 91 +++--- .../models/javaagent/IastReplayRequest.java | 123 ++++++++ .../models/javaagent/JAHealthCheck.java | 271 +++--------------- .../models/javaagent/SchedulerRuns.java | 70 +++++ .../javaagent/ThreadPoolActiveStat.java | 27 ++ .../models/javaagent/ThreadPoolStats.java | 60 ++-- .../javaagent/WebSocketConnectionStats.java | 92 ++++++ .../intcodeagent/schedulers/FileCleaner.java | 2 + .../intcodeagent/websocket/EventSendPool.java | 57 +--- .../intcodeagent/websocket/WSClient.java | 6 +- .../websocket/WSReconnectionST.java | 2 + .../newrelic/api/agent/security/Agent.java | 4 +- .../GrpcClientRequestReplayHelper.java | 3 + 26 files changed, 702 insertions(+), 418 deletions(-) create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/DroppedEvents.java create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventMetric.java create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/IastReplayRequest.java create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/SchedulerRuns.java create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ThreadPoolActiveStat.java create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/WebSocketConnectionStats.java diff --git a/gradle.properties b/gradle.properties index e0be6fcc8..73364766c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # The agent version. -agentVersion=1.3.0 +agentVersion=1.4.0 jsonVersion=1.2.1 # Updated exposed NR APM API version. nrAPIVersion=8.4.0 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..53ddbe534 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 @@ -311,6 +311,7 @@ private JavaAgentEventBean processFileOperationEvent(JavaAgentEventBean eventBea */ private void processReflectedXSSEvent(JavaAgentEventBean eventBean) { if (!NewRelic.getAgent().getConfig().getValue(INRSettingsKey.SECURITY_DETECTION_RXSS_ENABLED, true)) { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDroppedDueTo().incrementRxssDetectionDeactivated(); return; } Set xssConstructs = CallbackUtils.checkForReflectedXSS(securityMetaData.getRequest(), securityMetaData.getResponse()); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java index 4be77dfae..f317969a7 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java @@ -83,19 +83,18 @@ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { RestRequestThreadPool.getInstance().getRejectedIds().add(fuzzRequestId); } } - + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDispatcher().incrementRejected(); if(dispatcher.getSecurityMetaData() != null) { if(dispatcher.getSecurityMetaData().getFuzzRequestIdentifier().getK2Request()){ - AgentInfo.getInstance().getJaHealthCheck().getIastEventStats().incrementRejectedCount(); - } else { - AgentInfo.getInstance().getJaHealthCheck().getRaspEventStats().incrementRejectedCount(); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getIastEvents().incrementRejected(); + } + if(dispatcher.getOperation()!= null && dispatcher.getOperation().isLowSeverityHook()) { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getLowSeverityEvents().incrementRejected(); } } else if (dispatcher.getExitEventBean() != null) { - AgentInfo.getInstance().getJaHealthCheck().getExitEventStats().incrementRejectedCount(); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getExitEvents().incrementRejected(); } } - AgentInfo.getInstance().getJaHealthCheck().incrementDropCount(); - AgentInfo.getInstance().getJaHealthCheck().incrementEventRejectionCount(); logger.log(LogLevel.FINEST,"Event Dispatch Task " + r.toString() + " rejected from " + e.toString(), DispatcherPool.class.getName()); } } @@ -111,13 +110,35 @@ private DispatcherPool() { @Override protected void afterExecute(Runnable r, Throwable t) { try { - if( t != null) { - AgentInfo.getInstance().getJaHealthCheck().incrementDropCount(); - AgentInfo.getInstance().getJaHealthCheck().incrementEventProcessingErrorCount(); - incrementCount(r, IUtilConstants.ERROR); - } else { - AgentInfo.getInstance().getJaHealthCheck().incrementProcessedCount(); - incrementCount(r, IUtilConstants.PROCESSED); + if (r instanceof CustomFutureTask && ((CustomFutureTask) r).getTask() instanceof Dispatcher) { + Dispatcher dispatcher = (Dispatcher) ((CustomFutureTask) r).getTask(); + AbstractOperation operation = dispatcher.getOperation(); + SecurityMetaData securityMetaData = dispatcher.getSecurityMetaData(); + if(t != null){ + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDispatcher().incrementError(); + if(operation != null) { + if(securityMetaData != null && securityMetaData.getFuzzRequestIdentifier().getK2Request()) { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getIastEvents().incrementError(); + } + if (operation.isLowSeverityHook()) { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getLowSeverityEvents().incrementError(); + } + } else if (dispatcher.getExitEventBean() != null) { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getExitEvents().incrementError(); + } + } else { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDispatcher().incrementCompleted(); + if(operation != null) { + if(securityMetaData != null && securityMetaData.getFuzzRequestIdentifier().getK2Request()) { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getIastEvents().incrementCompleted(); + } + if (operation.isLowSeverityHook()) { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getLowSeverityEvents().incrementCompleted(); + } + } else if (dispatcher.getExitEventBean() != null) { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getExitEvents().incrementCompleted(); + } + } } } catch (Throwable ignored) { logger.log(LogLevel.FINEST, "Error while Dispatcher matric processing", ignored, DispatcherPool.class.getName()); @@ -145,41 +166,6 @@ public Thread newThread(Runnable r) { }); } - private void incrementCount(Runnable r, String type) { - EventStats eventStats = null; - if (r instanceof CustomFutureTask && ((CustomFutureTask) r).getTask() instanceof Dispatcher) { - Dispatcher dispatcher = (Dispatcher) ((CustomFutureTask) r).getTask(); - if(dispatcher.getSecurityMetaData() != null) { - if(dispatcher.getSecurityMetaData().getFuzzRequestIdentifier().getK2Request()){ - eventStats = AgentInfo.getInstance().getJaHealthCheck().getIastEventStats(); - } else { - eventStats = AgentInfo.getInstance().getJaHealthCheck().getRaspEventStats(); - } - } else if (dispatcher.getExitEventBean() != null) { - eventStats = AgentInfo.getInstance().getJaHealthCheck().getExitEventStats(); - } - } - if(eventStats == null){ - return; - } - switch (type){ - case IUtilConstants.ERROR: - eventStats.incrementErrorCount(); - break; - case IUtilConstants.PROCESSED: - eventStats.incrementProcessedCount(); - break; - case IUtilConstants.SENT: - eventStats.incrementSentCount(); - break; - case IUtilConstants.REJECTED: - eventStats.incrementRejectedCount(); - break; - default: - logger.log(LogLevel.FINEST, String.format("Couldn't update event matric for task :%s and type : %s", r, type), DispatcherPool.class.getName()); - } - } - private static final class InstanceHolder { static final DispatcherPool instance = new DispatcherPool(); } @@ -193,15 +179,14 @@ public Set getEid() { public void dispatchEvent(AbstractOperation operation, SecurityMetaData securityMetaData) { - AgentInfo.getInstance().getJaHealthCheck().incrementInvokedHookCount(); if (executor.isShutdown()) { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDroppedDueTo().incrementExecutorUnavailable(); return; } if(!securityMetaData.getFuzzRequestIdentifier().getK2Request() && !AgentUsageMetric.isRASPProcessingActive()){ - AgentInfo.getInstance().getJaHealthCheck().getRaspEventStats().incrementRejectedCount(); - AgentInfo.getInstance().getJaHealthCheck().incrementEventRejectionCount(); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDroppedDueTo().incrementRaspProcessingDeactivated(); return; } @@ -233,6 +218,14 @@ public void dispatchEvent(AbstractOperation operation, SecurityMetaData security securityMetaData.addCustomAttribute(NR_APM_TRACE_ID, traceMetadata.getTraceId()); securityMetaData.addCustomAttribute(NR_APM_SPAN_ID, traceMetadata.getSpanId()); this.executor.submit(new Dispatcher(operation, new SecurityMetaData(securityMetaData))); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDispatcher().incrementSubmitted(); + + if(securityMetaData.getFuzzRequestIdentifier().getK2Request()){ + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getIastEvents().incrementSubmitted(); + } + if(operation.isLowSeverityHook()){ + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getLowSeverityEvents().incrementSubmitted(); + } } public void dispatchExitEvent(ExitEventBean exitEventBean) { @@ -246,6 +239,7 @@ public void dispatchExitEvent(ExitEventBean exitEventBean) { securityMetaData.addCustomAttribute(NR_APM_TRACE_ID, traceMetadata.getTraceId()); securityMetaData.addCustomAttribute(NR_APM_SPAN_ID, traceMetadata.getSpanId()); this.executor.submit(new Dispatcher(exitEventBean)); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getExitEvents().incrementSubmitted(); } public static void shutDownPool() { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/EventAbortPolicy.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/EventAbortPolicy.java index 0dd26f8db..7a2595c9f 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/EventAbortPolicy.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/EventAbortPolicy.java @@ -1,5 +1,6 @@ package com.newrelic.agent.security.instrumentator.httpclient; +import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -11,6 +12,7 @@ public class EventAbortPolicy implements RejectedExecutionHandler { public EventAbortPolicy() { + AgentInfo.getInstance().getJaHealthCheck().getIastReplayRequest().incrementReplayRequestRejected(); } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestThreadPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestThreadPool.java index 779217700..e0238558e 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestThreadPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestThreadPool.java @@ -1,5 +1,6 @@ package com.newrelic.agent.security.instrumentator.httpclient; +import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.intcodeagent.executor.CustomFutureTask; import com.newrelic.agent.security.intcodeagent.executor.CustomThreadPoolExecutor; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java index f66a634d4..be5511579 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java @@ -1,6 +1,7 @@ package com.newrelic.agent.security.intcodeagent.controlcommand; import com.fasterxml.jackson.core.JsonProcessingException; +import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.httpclient.IASTDataTransferRequestProcessor; import com.newrelic.agent.security.instrumentator.httpclient.RestRequestProcessor; import com.newrelic.agent.security.instrumentator.httpclient.RestRequestThreadPool; @@ -165,6 +166,7 @@ public void run() { } break; case IntCodeControlCommand.FUZZ_REQUEST: + AgentInfo.getInstance().getJaHealthCheck().getIastReplayRequest().incrementReceivedControlCommands(); logger.log(LogLevel.FINER, FUZZ_REQUEST + controlCommandMessage, ControlCommandProcessor.class.getName()); IASTDataTransferRequestProcessor.getInstance().setLastFuzzCCTimestamp(Instant.now().toEpochMilli()); @@ -213,6 +215,7 @@ public void run() { * Post reconnect: reset 'reconnecting phase' in WSClient. */ try { + AgentInfo.getInstance().getJaHealthCheck().getWebSocketConnectionStats().incrementReceivedReconnectAtWill(); //TODO no need for draining IAST since last leg has complete ledger. logger.log(LogLevel.INFO, RECEIVED_WS_RECONNECT_COMMAND_FROM_SERVER_INITIATING_SEQUENCE, this.getClass().getName()); if (NewRelicSecurity.getAgent().getCurrentPolicy().getVulnerabilityScan().getEnabled() && diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java index 8f159ad04..804523cc4 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java @@ -27,6 +27,10 @@ public class ControlCommandProcessorThreadPool { private final boolean allowCoreThreadTimeOut = false; private static Object mutex = new Object(); + public ThreadPoolExecutor getExecutor() { + return executor; + } + /** * A handler for rejected tasks that throws a * {@code RejectedExecutionException}. diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java index 521f4cd75..0bc3c1376 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java @@ -192,4 +192,8 @@ public void setInitLoggingActive(boolean initLoggingActive) { public boolean isLogLevelEnabled(LogLevel logLevel) { return (logLevel.getLevel() >= LogWriter.defaultLogLevel); } + + public ThreadPoolExecutor getExecutor() { + return executor; + } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogFileHelper.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogFileHelper.java index 196dba274..dcbab5f37 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogFileHelper.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogFileHelper.java @@ -7,6 +7,7 @@ package com.newrelic.agent.security.intcodeagent.filelogging; +import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.intcodeagent.properties.K2JALogProperties; import com.newrelic.agent.security.util.IUtilConstants; @@ -92,6 +93,7 @@ public static BufferedWriter dailyRollover(String fileName) throws IOException { public static void performDailyRollover(){ try { + AgentInfo.getInstance().getJaHealthCheck().getSchedulerRuns().incrementDailyLogRollover(); InitLogWriter.setWriter(dailyRollover(InitLogWriter.getFileName())); } catch (IOException e) { FileLoggerThreadPool.getInstance().setInitLoggingActive(false); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java index 5d71a79d1..a33da7bbe 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java @@ -7,7 +7,10 @@ import com.newrelic.agent.security.instrumentator.os.OSVariables; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.instrumentator.utils.AgentUtils; +import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessorThreadPool; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; +import com.newrelic.agent.security.intcodeagent.models.javaagent.ThreadPoolActiveStat; +import com.newrelic.api.agent.security.instrumentation.helpers.GrpcClientRequestReplayHelper; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.models.javaagent.JAHealthCheck; import com.newrelic.agent.security.intcodeagent.models.javaagent.ThreadPoolStats; @@ -76,7 +79,8 @@ public void run() { } logger.log(LogLevel.INFO, String.format("Pending CCs to be processed : %s", RestRequestThreadPool.getInstance().getQueueSize()), this.getClass().getName()); - AgentInfo.getInstance().getJaHealthCheck().setDsBackLog(RestRequestThreadPool.getInstance().getQueueSize()); + AgentInfo.getInstance().getJaHealthCheck().getIastReplayRequest().incrementPendingControlCommandsBy(RestRequestThreadPool.getInstance().getQueueSize()); + AgentInfo.getInstance().getJaHealthCheck().getIastReplayRequest().incrementPendingControlCommandsBy(GrpcClientRequestReplayHelper.getInstance().getRequestQueue().size()); AgentUtils.getInstance().addStatusLogMostRecentHCs(AgentInfo.getInstance().getJaHealthCheck().toString()); // channel.write(ByteBuffer.wrap(new JAHealthCheck(AgentNew.JA_HEALTH_CHECK).toString().getBytes())); if (WSClient.getInstance().isOpen()) { @@ -101,15 +105,24 @@ public void run() { private ThreadPoolStats populateThreadPoolStats() { ThreadPoolStats threadPoolStats = new ThreadPoolStats(); - threadPoolStats.setDispatcherQueueSize(DispatcherPool.getInstance().getExecutor().getQueue().size()); - threadPoolStats.setEventSendQueueSize(EventSendPool.getInstance().getExecutor().getQueue().size()); + threadPoolStats.setDispatcher(new ThreadPoolActiveStat(DispatcherPool.getInstance().getExecutor().getActiveCount(), + DispatcherPool.getInstance().getExecutor().getQueue().size())); + threadPoolStats.setEventSender(new ThreadPoolActiveStat(EventSendPool.getInstance().getExecutor().getActiveCount(), + EventSendPool.getInstance().getExecutor().getQueue().size())); + threadPoolStats.setControlCommandProcessor(new ThreadPoolActiveStat(ControlCommandProcessorThreadPool.getInstance().getExecutor().getActiveCount(), + ControlCommandProcessorThreadPool.getInstance().getExecutor().getQueue().size())); + threadPoolStats.setIastHttpRequestProcessor(new ThreadPoolActiveStat(RestRequestThreadPool.getInstance().getExecutor().getActiveCount(), + RestRequestThreadPool.getInstance().getExecutor().getQueue().size())); + threadPoolStats.setFileLogger(new ThreadPoolActiveStat(FileLoggerThreadPool.getInstance().getExecutor().getActiveCount(), + FileLoggerThreadPool.getInstance().getExecutor().getQueue().size())); + return threadPoolStats; } private HealthCheckScheduleThread() {} public void scheduleNewTask() { - future = SchedulerHelper.getInstance().scheduleHealthCheck(runnable, 30, 300, TimeUnit.SECONDS); + future = SchedulerHelper.getInstance().scheduleHealthCheck(runnable, 30, 30, TimeUnit.SECONDS); } public boolean cancelTask(boolean forceCancel) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java index c290ea86a..04b45b83c 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java @@ -59,6 +59,8 @@ public class AgentBasicInfo { private Map linkingMetadata; + private String accountId; + @JsonInclude private static String policyVersion; @@ -75,6 +77,7 @@ public AgentBasicInfo() { setGroupName(AgentConfig.getInstance().getGroupName()); setNodeId(AgentInfo.getInstance().getLinkingMetadata().getOrDefault(INRSettingsKey.NR_ENTITY_GUID, StringUtils.EMPTY)); setLinkingMetadata(new HashMap<>(AgentInfo.getInstance().getLinkingMetadata())); + setAccountId(AgentConfig.getInstance().getConfig().getCustomerInfo().getAccountId()); if (this instanceof ApplicationInfoBean) { setJsonName(JSON_NAME_APPLICATION_INFO_BEAN); } else if (this instanceof JavaAgentEventBean) { @@ -223,6 +226,13 @@ public void setPolicyOverridden(boolean policyOverridden) { isPolicyOverridden = policyOverridden; } + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } public Map getLinkingMetadata() { return linkingMetadata; diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/DroppedEvents.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/DroppedEvents.java new file mode 100644 index 000000000..647fdea2a --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/DroppedEvents.java @@ -0,0 +1,94 @@ +package com.newrelic.agent.security.intcodeagent.models.javaagent; + +import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; + +import java.util.concurrent.atomic.AtomicInteger; + +public class DroppedEvents { + + private AtomicInteger unsupportedContentType = new AtomicInteger(); + + private AtomicInteger nrInternalEvent = new AtomicInteger(); + + private AtomicInteger csecInternalEvent = new AtomicInteger(); + + private AtomicInteger executorUnavailable = new AtomicInteger(); + + private AtomicInteger raspProcessingDeactivated = new AtomicInteger(); + + private AtomicInteger rxssDetectionDeactivated = new AtomicInteger(); + + public DroppedEvents() { + } + + public DroppedEvents(DroppedEvents droppedEvents) { + this.unsupportedContentType.set(droppedEvents.unsupportedContentType.get()); + this.nrInternalEvent.set(droppedEvents.nrInternalEvent.get()); + this.csecInternalEvent.set(droppedEvents.csecInternalEvent.get()); + this.executorUnavailable.set(droppedEvents.executorUnavailable.get()); + this.raspProcessingDeactivated.set(droppedEvents.raspProcessingDeactivated.get()); + this.rxssDetectionDeactivated.set(droppedEvents.rxssDetectionDeactivated.get()); + } + + public AtomicInteger getUnsupportedContentType() { + return unsupportedContentType; + } + + public AtomicInteger getNrInternalEvent() { + return nrInternalEvent; + } + + public AtomicInteger getCsecInternalEvent() { + return csecInternalEvent; + } + + public void incrementUnsupportedContentType() { + unsupportedContentType.incrementAndGet(); + } + + public void incrementNrInternalEvent() { + nrInternalEvent.incrementAndGet(); + } + + public void incrementCsecInternalEvent() { + csecInternalEvent.incrementAndGet(); + } + + public AtomicInteger getExecutorUnavailable() { + return executorUnavailable; + } + + public void incrementExecutorUnavailable() { + executorUnavailable.incrementAndGet(); + } + + public AtomicInteger getRaspProcessingDeactivated() { + return raspProcessingDeactivated; + } + + public void incrementRaspProcessingDeactivated() { + raspProcessingDeactivated.incrementAndGet(); + } + + public AtomicInteger getRxssDetectionDeactivated() { + return rxssDetectionDeactivated; + } + + public void incrementRxssDetectionDeactivated() { + rxssDetectionDeactivated.incrementAndGet(); + } + + public void reset(){ + unsupportedContentType.set(0); + nrInternalEvent.set(0); + csecInternalEvent.set(0); + executorUnavailable.set(0); + raspProcessingDeactivated.set(0); + rxssDetectionDeactivated.set(0); + } + + @Override + public String toString() { + return JsonConverter.toJSON(this); + } +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventMetric.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventMetric.java new file mode 100644 index 000000000..282876235 --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventMetric.java @@ -0,0 +1,70 @@ +package com.newrelic.agent.security.intcodeagent.models.javaagent; + +import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; + +import java.util.concurrent.atomic.AtomicInteger; + +public class EventMetric { + + private AtomicInteger submitted = new AtomicInteger(0); + + private AtomicInteger completed = new AtomicInteger(0); + + private AtomicInteger rejected = new AtomicInteger(0); + + private AtomicInteger error = new AtomicInteger(0); + + public EventMetric() { + } + + public EventMetric(EventMetric eventMetric) { + this.submitted.set(eventMetric.submitted.get()); + this.completed.set(eventMetric.completed.get()); + this.rejected.set(eventMetric.rejected.get()); + this.error.set(eventMetric.error.get()); + } + + public AtomicInteger getSubmitted() { + return submitted; + } + + public AtomicInteger getCompleted() { + return completed; + } + + public AtomicInteger getRejected() { + return rejected; + } + + public AtomicInteger getError() { + return error; + } + + public int incrementSubmitted() { + return submitted.incrementAndGet(); + } + + public int incrementCompleted() { + return completed.incrementAndGet(); + } + + public int incrementRejected() { + return rejected.incrementAndGet(); + } + + public int incrementError() { + return error.incrementAndGet(); + } + + @Override + public String toString() { + return JsonConverter.toJSON(this); + } + + public void reset(){ + submitted.set(0); + completed.set(0); + rejected.set(0); + error.set(0); + } +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventStats.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventStats.java index 86d3037cf..279dcb401 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventStats.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventStats.java @@ -6,86 +6,63 @@ public class EventStats { - private AtomicInteger processed; + private EventMetric eventSender = new EventMetric(); - private AtomicInteger sent; + private EventMetric iastEvents = new EventMetric(); - private AtomicInteger rejected; + private EventMetric dispatcher = new EventMetric(); - private AtomicInteger errorCount; + private DroppedEvents droppedDueTo = new DroppedEvents(); - public EventStats() { - this.processed = new AtomicInteger(0); - this.sent = new AtomicInteger(0); - this.rejected = new AtomicInteger(0); - this.errorCount = new AtomicInteger(0); - } - - public EventStats(EventStats eventStats) { - this.processed = new AtomicInteger(eventStats.processed.intValue()); - this.sent = new AtomicInteger(eventStats.sent.intValue()); - this.rejected = new AtomicInteger(eventStats.rejected.intValue()); - this.errorCount = new AtomicInteger(eventStats.errorCount.intValue()); - } - - public AtomicInteger getProcessed() { - return processed; - } - - public void setProcessed(AtomicInteger processed) { - this.processed = processed; - } - - public AtomicInteger getSent() { - return sent; - } + private EventMetric lowSeverityEvents = new EventMetric(); - public void setSent(AtomicInteger sent) { - this.sent = sent; - } + private EventMetric exitEvents = new EventMetric(); - public AtomicInteger getRejected() { - return rejected; + public EventStats() { } - public void setRejected(AtomicInteger rejected) { - this.rejected = rejected; + public EventStats(EventStats eventStats) { + this.eventSender = new EventMetric(eventStats.eventSender); + this.iastEvents = new EventMetric(eventStats.iastEvents); + this.dispatcher = new EventMetric(eventStats.dispatcher); + this.droppedDueTo = new DroppedEvents(eventStats.droppedDueTo); + this.lowSeverityEvents = new EventMetric(eventStats.lowSeverityEvents); + this.exitEvents = new EventMetric(eventStats.exitEvents); } - public int incrementRejectedCount(){ - return this.rejected.incrementAndGet(); + public void reset(){ + this.lowSeverityEvents.reset(); + this.eventSender.reset(); + this.iastEvents.reset(); + this.dispatcher.reset(); + this.exitEvents.reset(); } - public int incrementSentCount(){ - return this.sent.incrementAndGet(); + public String toString() { + return JsonConverter.toJSON(this); } - public int incrementProcessedCount(){ - return this.processed.incrementAndGet(); + public EventMetric getLowSeverityEvents() { + return lowSeverityEvents; } - public int incrementErrorCount(){ - return this.errorCount.incrementAndGet(); + public EventMetric getEventSender() { + return eventSender; } - public AtomicInteger getErrorCount() { - return errorCount; + public EventMetric getIastEvents() { + return iastEvents; } - public void setErrorCount(AtomicInteger errorCount) { - this.errorCount = errorCount; + public EventMetric getDispatcher() { + return dispatcher; } - public void reset(){ - this.processed.set(0); - this.sent.set(0); - this.errorCount.set(0); - this.rejected.set(0); + public DroppedEvents getDroppedDueTo() { + return droppedDueTo; } - - - public String toString() { - return JsonConverter.toJSON(this); + public EventMetric getExitEvents() { + return exitEvents; } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/IastReplayRequest.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/IastReplayRequest.java new file mode 100644 index 000000000..15b9dba2f --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/IastReplayRequest.java @@ -0,0 +1,123 @@ +package com.newrelic.agent.security.intcodeagent.models.javaagent; + +import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; + +import java.util.concurrent.atomic.AtomicInteger; + +public class IastReplayRequest { + + private AtomicInteger receivedControlCommands = new AtomicInteger(); + + private AtomicInteger processedControlCommands = new AtomicInteger(); + + private AtomicInteger pendingControlCommands = new AtomicInteger(); + + private AtomicInteger replayRequestGenerated = new AtomicInteger(); + + private AtomicInteger replayRequestExecuted = new AtomicInteger(); + + private AtomicInteger replayRequestSucceeded = new AtomicInteger(); + + private AtomicInteger replayRequestFailed = new AtomicInteger(); + + private AtomicInteger replayRequestRejected = new AtomicInteger(); + + public IastReplayRequest() { + } + + public IastReplayRequest(IastReplayRequest iastReplayRequest) { + this.receivedControlCommands.set(iastReplayRequest.getReceivedControlCommands().get()); + this.processedControlCommands.set(iastReplayRequest.getProcessedControlCommands().get()); + this.pendingControlCommands.set(iastReplayRequest.getPendingControlCommands().get()); + this.replayRequestGenerated.set(iastReplayRequest.getReplayRequestGenerated().get()); + this.replayRequestExecuted.set(iastReplayRequest.getReplayRequestExecuted().get()); + this.replayRequestSucceeded.set(iastReplayRequest.getReplayRequestSucceeded().get()); + this.replayRequestFailed.set(iastReplayRequest.getReplayRequestFailed().get()); + this.replayRequestRejected.set(iastReplayRequest.getReplayRequestRejected().get()); + } + + public AtomicInteger getReceivedControlCommands() { + return receivedControlCommands; + } + + public AtomicInteger getProcessedControlCommands() { + return processedControlCommands; + } + + public AtomicInteger getPendingControlCommands() { + return pendingControlCommands; + } + + public AtomicInteger getReplayRequestGenerated() { + return replayRequestGenerated; + } + + public AtomicInteger getReplayRequestExecuted() { + return replayRequestExecuted; + } + + public AtomicInteger getReplayRequestSucceeded() { + return replayRequestSucceeded; + } + + public AtomicInteger getReplayRequestFailed() { + return replayRequestFailed; + } + + public AtomicInteger getReplayRequestRejected() { + return replayRequestRejected; + } + + public int incrementReceivedControlCommands() { + return receivedControlCommands.incrementAndGet(); + } + + public int incrementProcessedControlCommands() { + return processedControlCommands.incrementAndGet(); + } + + public int incrementPendingControlCommands() { + return pendingControlCommands.incrementAndGet(); + } + + public int incrementReplayRequestGenerated() { + return replayRequestGenerated.incrementAndGet(); + } + + public int incrementReplayRequestExecuted() { + return replayRequestExecuted.incrementAndGet(); + } + + public int incrementReplayRequestSucceeded() { + return replayRequestSucceeded.incrementAndGet(); + } + + public int incrementReplayRequestFailed() { + return replayRequestFailed.incrementAndGet(); + } + + public int incrementReplayRequestRejected() { + return replayRequestRejected.incrementAndGet(); + } + + public void incrementPendingControlCommandsBy(int count) { + pendingControlCommands.addAndGet(count); + } + + public void reset() { + receivedControlCommands.set(0); + processedControlCommands.set(0); + pendingControlCommands.set(0); + replayRequestGenerated.set(0); + replayRequestExecuted.set(0); + replayRequestSucceeded.set(0); + replayRequestFailed.set(0); + replayRequestRejected.set(0); + } + + public String toString() { + return JsonConverter.toJSON(this); + } + + +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java index da4d409cf..25c43f42d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java @@ -16,37 +16,11 @@ public class JAHealthCheck extends AgentBasicInfo { private String applicationUUID; -// private String protectedServer; - -// private Set protectedDB; - private AtomicInteger invokedHookCount; - private AtomicInteger eventDropCount; - - private AtomicInteger eventRejectionCount; - - private AtomicInteger eventProcessingErrorCount; - - private AtomicInteger eventSendRejectionCount; - - private AtomicInteger eventSendErrorCount; - private IdentifierEnvs kind; - private AtomicInteger eventProcessed; - - private AtomicInteger eventSentCount; - - private AtomicInteger exitEventSentCount; - - private AtomicInteger httpRequestCount; - - private EventStats raspEventStats; - - private EventStats iastEventStats; - - private EventStats exitEventStats; + private EventStats eventStats; private ThreadPoolStats threadPoolStats; @@ -54,29 +28,21 @@ public class JAHealthCheck extends AgentBasicInfo { private Map serviceStatus; -// private Set protectedVulnerabilities; + private IastReplayRequest iastReplayRequest = new IastReplayRequest(); + + private WebSocketConnectionStats webSocketConnectionStats = new WebSocketConnectionStats(); + + private SchedulerRuns schedulerRuns = new SchedulerRuns(); - private Integer dsBackLog; public JAHealthCheck(String applicationUUID) { super(); this.applicationUUID = applicationUUID; this.invokedHookCount = new AtomicInteger(0); - this.eventDropCount = new AtomicInteger(0); - this.eventProcessed = new AtomicInteger(0); - this.eventSentCount = new AtomicInteger(0); - this.httpRequestCount = new AtomicInteger(0); - this.exitEventSentCount = new AtomicInteger(0); - this.eventRejectionCount = new AtomicInteger(0); - this.eventProcessingErrorCount = new AtomicInteger(0); - this.eventSendRejectionCount = new AtomicInteger(0); - this.eventSendErrorCount = new AtomicInteger(0); - this.raspEventStats = new EventStats(); - this.iastEventStats = new EventStats(); - this.exitEventStats = new EventStats(); this.threadPoolStats = new ThreadPoolStats(); this.stats = new HashMap<>(); this.serviceStatus = new HashMap<>(); + this.eventStats = new EventStats(); this.setKind(AgentInfo.getInstance().getApplicationInfo().getIdentifier().getKind()); logger.log(LogLevel.INFO, String.format(HC_CREATED, JsonConverter.toJSON(this)), JAHealthCheck.class.getName()); } @@ -84,24 +50,15 @@ public JAHealthCheck(String applicationUUID) { public JAHealthCheck(JAHealthCheck jaHealthCheck) { super(); this.applicationUUID = jaHealthCheck.applicationUUID; - this.invokedHookCount = new AtomicInteger(jaHealthCheck.invokedHookCount.intValue()); - this.eventDropCount = new AtomicInteger(jaHealthCheck.eventDropCount.intValue()); - this.eventProcessed = new AtomicInteger(jaHealthCheck.eventProcessed.intValue()); - this.eventSentCount = new AtomicInteger(jaHealthCheck.eventSentCount.intValue()); - this.exitEventSentCount = new AtomicInteger(jaHealthCheck.exitEventSentCount.intValue()); - this.httpRequestCount = new AtomicInteger(jaHealthCheck.httpRequestCount.intValue()); - this.eventRejectionCount = new AtomicInteger(jaHealthCheck.eventRejectionCount.intValue()); - this.eventProcessingErrorCount = new AtomicInteger(jaHealthCheck.eventProcessingErrorCount.intValue()); - this.eventSendRejectionCount = new AtomicInteger(jaHealthCheck.eventSendRejectionCount.intValue()); - this.eventSendErrorCount = new AtomicInteger(jaHealthCheck.eventSendErrorCount.intValue()); - this.raspEventStats = new EventStats(jaHealthCheck.raspEventStats); - this.iastEventStats = new EventStats(jaHealthCheck.iastEventStats); - this.exitEventStats = new EventStats(jaHealthCheck.exitEventStats); this.threadPoolStats = new ThreadPoolStats(jaHealthCheck.threadPoolStats); this.kind = jaHealthCheck.kind; this.stats = new HashMap<>(jaHealthCheck.stats); this.serviceStatus = new HashMap<>(jaHealthCheck.serviceStatus); - this.dsBackLog = jaHealthCheck.dsBackLog; + this.eventStats = new EventStats(jaHealthCheck.eventStats); + this.iastReplayRequest = new IastReplayRequest(jaHealthCheck.iastReplayRequest); + this.schedulerRuns = new SchedulerRuns(jaHealthCheck.schedulerRuns); + this.invokedHookCount = new AtomicInteger(jaHealthCheck.invokedHookCount.get()); + this.webSocketConnectionStats = new WebSocketConnectionStats(jaHealthCheck.webSocketConnectionStats); logger.log(LogLevel.INFO, String.format(HC_CREATED, JsonConverter.toJSON(this)), JAHealthCheck.class.getName()); } @@ -127,157 +84,11 @@ public void setApplicationUUID(String applicationUUID) { this.applicationUUID = applicationUUID; } - /** - * @return the eventDropCount - */ - public Integer getEventDropCount() { - return eventDropCount.get(); - } - - /** - * @param eventDropCount the eventDropCount to set - */ - public void setEventDropCount(Integer eventDropCount) { - this.eventDropCount.set(eventDropCount); - } - - public void incrementDropCount() { - this.eventDropCount.getAndIncrement(); - } - - public AtomicInteger getEventRejectionCount() { - return eventRejectionCount; - } - - public void setEventRejectionCount(int eventRejectionCount) { - this.eventRejectionCount.set(eventRejectionCount); - } - - public int incrementEventRejectionCount(){ - return eventRejectionCount.incrementAndGet(); - } - - public AtomicInteger getEventProcessingErrorCount() { - return eventProcessingErrorCount; - } - - public void setEventProcessingErrorCount(int eventProcessingErrorCount) { - this.eventProcessingErrorCount.set(eventProcessingErrorCount); - } - - public int incrementEventProcessingErrorCount() { - return eventProcessingErrorCount.incrementAndGet(); - } - - public AtomicInteger getEventSendRejectionCount() { - return eventSendRejectionCount; - } - - public void setEventSendRejectionCount(int eventSendRejectionCount) { - this.eventSendRejectionCount.set(eventSendRejectionCount); - } - - public int incrementEventSendRejectionCount() { - return this.eventSendRejectionCount.incrementAndGet(); - } - - public AtomicInteger getEventSendErrorCount() { - return eventSendErrorCount; - } - - public void setEventSendErrorCount(int eventSendErrorCount) { - this.eventSendErrorCount.set(eventSendErrorCount); - } - - public int incrementEventSendErrorCount() { - return this.eventSendErrorCount.incrementAndGet(); - } - - public void incrementProcessedCount() { - this.eventProcessed.getAndIncrement(); - } - - public void incrementEventSentCount() { - this.eventSentCount.getAndIncrement(); - } - - public void decrementEventSentCount() { - this.eventSentCount.getAndDecrement(); - } - - public AtomicInteger getExitEventSentCount() { - return exitEventSentCount; - } - - public AtomicInteger getHttpRequestCount() { - return httpRequestCount; - } - - public void incrementHttpRequestCount() { - this.httpRequestCount.getAndIncrement(); - } - - public void decrementHttpRequestCount() { - this.httpRequestCount.getAndDecrement(); - } - - public void incrementExitEventSentCount() { - this.exitEventSentCount.getAndIncrement(); - } - - public void decrementExitEventSentCount() { - this.exitEventSentCount.getAndDecrement(); - } - - public void setExitEventSentCount(Integer exitEventSentCount) { - this.exitEventSentCount.set(exitEventSentCount); - } - @Override public String toString() { return JsonConverter.toJSON(this); } - /** - * @return the eventProcessed - */ - public Integer getEventProcessed() { - return eventProcessed.get(); - } - - /** - * @param eventProcessed the eventProcessed to set - */ - public void setEventProcessed(Integer eventProcessed) { - this.eventProcessed.set(eventProcessed); - } - - /** - * @return the eventSentCount - */ - public AtomicInteger getEventSentCount() { - return eventSentCount; - } - - /** - * @param eventSentCount the eventSentCount to set - */ - public void setEventSentCount(Integer eventSentCount) { - this.eventSentCount.set(eventSentCount); - } - - public void setHttpRequestCount(Integer httpRequestCount) { - this.httpRequestCount.set(httpRequestCount); - } - - public Integer getDsBackLog() { - return dsBackLog; - } - - public void setDsBackLog(Integer dsBackLog) { - this.dsBackLog = dsBackLog; - } - public Map getStats() { return stats; } @@ -294,21 +105,6 @@ public void setServiceStatus(Map serviceStatus) { this.serviceStatus = serviceStatus; } - public EventStats getRaspEventStats() { - return raspEventStats; - } - - public void setRaspEventStats(EventStats raspEventStats) { - this.raspEventStats = raspEventStats; - } - - public EventStats getIastEventStats() { - return iastEventStats; - } - - public void setIastEventStats(EventStats iastEventStats) { - this.iastEventStats = iastEventStats; - } public ThreadPoolStats getThreadPoolStats() { return threadPoolStats; @@ -318,13 +114,6 @@ public void setThreadPoolStats(ThreadPoolStats threadPoolStats) { this.threadPoolStats = threadPoolStats; } - public EventStats getExitEventStats() { - return exitEventStats; - } - - public void setExitEventStats(EventStats exitEventStats) { - this.exitEventStats = exitEventStats; - } public int getInvokedHookCount() { return invokedHookCount.get(); @@ -338,21 +127,33 @@ public int incrementInvokedHookCount() { return invokedHookCount.incrementAndGet(); } + public EventStats getEventStats() { + return eventStats; + } + + public IastReplayRequest getIastReplayRequest() { + return iastReplayRequest; + } + + public WebSocketConnectionStats getWebSocketConnectionStats() { + return webSocketConnectionStats; + } + + public SchedulerRuns getSchedulerRuns() { + return schedulerRuns; + } + + public void setSchedulerRuns(SchedulerRuns schedulerRuns) { + this.schedulerRuns = schedulerRuns; + } + public void reset(){ - this.setEventDropCount(0); this.setInvokedHookCount(0); - this.setEventProcessed(0); - this.setEventSentCount(0); - this.setHttpRequestCount(0); - this.setExitEventSentCount(0); - this.setEventRejectionCount(0); - this.setEventProcessingErrorCount(0); - this.setEventSendRejectionCount(0); - this.setEventSendErrorCount(0); - this.raspEventStats.reset(); - this.iastEventStats.reset(); - this.exitEventStats.reset(); this.stats.clear(); this.serviceStatus.clear(); + this.eventStats.reset(); + this.iastReplayRequest.reset(); + this.webSocketConnectionStats.reset(); + this.schedulerRuns.reset(); } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/SchedulerRuns.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/SchedulerRuns.java new file mode 100644 index 000000000..6fcb650f1 --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/SchedulerRuns.java @@ -0,0 +1,70 @@ +package com.newrelic.agent.security.intcodeagent.models.javaagent; + +import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; + +import java.util.concurrent.atomic.AtomicInteger; + +public class SchedulerRuns { + + private AtomicInteger iastFileCleaner = new AtomicInteger(); + + private AtomicInteger lowPriorityFilterCleaner = new AtomicInteger(); + + private AtomicInteger dailyLogRollover = new AtomicInteger(); + + private AtomicInteger websocketReconnector = new AtomicInteger(); + + public SchedulerRuns() { + } + + public SchedulerRuns(SchedulerRuns schedulerRuns) { + iastFileCleaner.set(schedulerRuns.iastFileCleaner.get()); + lowPriorityFilterCleaner.set(schedulerRuns.lowPriorityFilterCleaner.get()); + dailyLogRollover.set(schedulerRuns.dailyLogRollover.get()); + websocketReconnector.set(schedulerRuns.websocketReconnector.get()); + } + + public AtomicInteger getIastFileCleaner() { + return iastFileCleaner; + } + + public AtomicInteger getLowPriorityFilterCleaner() { + return lowPriorityFilterCleaner; + } + + public AtomicInteger getDailyLogRollover() { + return dailyLogRollover; + } + + public AtomicInteger getWebsocketReconnector() { + return websocketReconnector; + } + + public int incrementIastFileCleaner() { + return iastFileCleaner.incrementAndGet(); + } + + public int incrementLowPriorityFilterCleaner() { + return lowPriorityFilterCleaner.incrementAndGet(); + } + + public int incrementDailyLogRollover() { + return dailyLogRollover.incrementAndGet(); + } + + public int incrementWebsocketReconnector() { + return websocketReconnector.incrementAndGet(); + } + + @Override + public String toString() { + return JsonConverter.toJSON(this); + } + + public void reset() { + iastFileCleaner.set(0); + lowPriorityFilterCleaner.set(0); + dailyLogRollover.set(0); + websocketReconnector.set(0); + } +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ThreadPoolActiveStat.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ThreadPoolActiveStat.java new file mode 100644 index 000000000..1d5d6989a --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ThreadPoolActiveStat.java @@ -0,0 +1,27 @@ +package com.newrelic.agent.security.intcodeagent.models.javaagent; + +import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; + +public class ThreadPoolActiveStat { + + private Integer activeThreadCount; + + private Integer currentQueueSize; + + public ThreadPoolActiveStat(Integer activeThreadCount, Integer currentQueueSize) { + this.activeThreadCount = activeThreadCount; + this.currentQueueSize = currentQueueSize; + } + + public Integer getActiveThreadCount() { + return activeThreadCount; + } + + public Integer getCurrentQueueSize() { + return currentQueueSize; + } + + public String toString() { + return JsonConverter.toJSON(this); + } +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ThreadPoolStats.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ThreadPoolStats.java index 880284e87..abc0238af 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ThreadPoolStats.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ThreadPoolStats.java @@ -4,39 +4,67 @@ public class ThreadPoolStats { - private Integer dispatcherQueueSize; + private ThreadPoolActiveStat dispatcher; - private Integer eventSendQueueSize; + private ThreadPoolActiveStat eventSender; + + private ThreadPoolActiveStat fileLogger; + + private ThreadPoolActiveStat iastHttpRequestProcessor; + + private ThreadPoolActiveStat controlCommandProcessor; public ThreadPoolStats() { } - public ThreadPoolStats(Integer dispatcherQueueSize, Integer eventSendQueueSize) { - this.dispatcherQueueSize = dispatcherQueueSize; - this.eventSendQueueSize = eventSendQueueSize; + public ThreadPoolStats(ThreadPoolStats threadPoolStats) { + this.dispatcher = new ThreadPoolActiveStat(threadPoolStats.dispatcher.getActiveThreadCount(), threadPoolStats.dispatcher.getCurrentQueueSize()); + this.eventSender = new ThreadPoolActiveStat(threadPoolStats.eventSender.getActiveThreadCount(), threadPoolStats.eventSender.getCurrentQueueSize()); + this.fileLogger = new ThreadPoolActiveStat(threadPoolStats.fileLogger.getActiveThreadCount(), threadPoolStats.fileLogger.getCurrentQueueSize()); + this.iastHttpRequestProcessor = new ThreadPoolActiveStat(threadPoolStats.iastHttpRequestProcessor.getActiveThreadCount(), threadPoolStats.iastHttpRequestProcessor.getCurrentQueueSize()); + this.controlCommandProcessor = new ThreadPoolActiveStat(threadPoolStats.controlCommandProcessor.getActiveThreadCount(), threadPoolStats.controlCommandProcessor.getCurrentQueueSize()); + + } + + public ThreadPoolActiveStat getDispatcher() { + return dispatcher; } - public ThreadPoolStats(ThreadPoolStats threadPoolStats) { - this.dispatcherQueueSize = threadPoolStats.dispatcherQueueSize; - this.eventSendQueueSize = threadPoolStats.eventSendQueueSize; + public ThreadPoolActiveStat getEventSender() { + return eventSender; } - public Integer getDispatcherQueueSize() { - return dispatcherQueueSize; + public ThreadPoolActiveStat getFileLogger() { + return fileLogger; } - public void setDispatcherQueueSize(Integer dispatcherQueueSize) { - this.dispatcherQueueSize = dispatcherQueueSize; + public ThreadPoolActiveStat getIastHttpRequestProcessor() { + return iastHttpRequestProcessor; } - public Integer getEventSendQueueSize() { - return eventSendQueueSize; + public ThreadPoolActiveStat getControlCommandProcessor() { + return controlCommandProcessor; } - public void setEventSendQueueSize(Integer eventSendQueueSize) { - this.eventSendQueueSize = eventSendQueueSize; + public void setDispatcher(ThreadPoolActiveStat dispatcher) { + this.dispatcher = dispatcher; } + public void setEventSender(ThreadPoolActiveStat eventSender) { + this.eventSender = eventSender; + } + + public void setFileLogger(ThreadPoolActiveStat fileLogger) { + this.fileLogger = fileLogger; + } + + public void setIastHttpRequestProcessor(ThreadPoolActiveStat iastHttpRequestProcessor) { + this.iastHttpRequestProcessor = iastHttpRequestProcessor; + } + + public void setControlCommandProcessor(ThreadPoolActiveStat controlCommandProcessor) { + this.controlCommandProcessor = controlCommandProcessor; + } public String toString() { return JsonConverter.toJSON(this); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/WebSocketConnectionStats.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/WebSocketConnectionStats.java new file mode 100644 index 000000000..9c3070aa2 --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/WebSocketConnectionStats.java @@ -0,0 +1,92 @@ +package com.newrelic.agent.security.intcodeagent.models.javaagent; + +import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; + +import java.util.concurrent.atomic.AtomicInteger; + +public class WebSocketConnectionStats { + + private AtomicInteger messagesSent = new AtomicInteger(); + + private AtomicInteger messagesReceived = new AtomicInteger(); + + private AtomicInteger connectionReconnected = new AtomicInteger(); + + private AtomicInteger connectionFailure = new AtomicInteger(); + + private AtomicInteger receivedReconnectAtWill = new AtomicInteger(); + + private AtomicInteger sendFailure = new AtomicInteger(); + + public WebSocketConnectionStats() { + } + + public WebSocketConnectionStats(WebSocketConnectionStats stats) { + messagesSent.set(stats.messagesSent.get()); + messagesReceived.set(stats.messagesReceived.get()); + connectionReconnected.set(stats.connectionReconnected.get()); + connectionFailure.set(stats.connectionFailure.get()); + receivedReconnectAtWill.set(stats.receivedReconnectAtWill.get()); + sendFailure.set(stats.sendFailure.get()); + } + + public AtomicInteger getMessagesSent() { + return messagesSent; + } + + public AtomicInteger getMessagesReceived() { + return messagesReceived; + } + + public AtomicInteger getConnectionReconnected() { + return connectionReconnected; + } + + public AtomicInteger getConnectionFailure() { + return connectionFailure; + } + + public AtomicInteger getReceivedReconnectAtWill() { + return receivedReconnectAtWill; + } + + public AtomicInteger getSendFailure() { + return sendFailure; + } + + public int incrementMessagesSent() { + return messagesSent.incrementAndGet(); + } + + public int incrementMessagesReceived() { + return messagesReceived.incrementAndGet(); + } + + public int incrementConnectionReconnected() { + return connectionReconnected.incrementAndGet(); + } + + public int incrementConnectionFailure() { + return connectionFailure.incrementAndGet(); + } + + public int incrementReceivedReconnectAtWill() { + return receivedReconnectAtWill.incrementAndGet(); + } + + public int incrementSendFailure() { + return sendFailure.incrementAndGet(); + } + + public void reset() { + messagesSent.set(0); + messagesReceived.set(0); + connectionReconnected.set(0); + connectionFailure.set(0); + receivedReconnectAtWill.set(0); + } + + public String toString() { + return JsonConverter.toJSON(this); + } +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/FileCleaner.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/FileCleaner.java index 7659ac8bf..f1ef38a90 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/FileCleaner.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/FileCleaner.java @@ -1,5 +1,6 @@ package com.newrelic.agent.security.intcodeagent.schedulers; +import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.os.OSVariables; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; @@ -30,6 +31,7 @@ public class FileCleaner { @Override public void run() { + AgentInfo.getInstance().getJaHealthCheck().getSchedulerRuns().incrementIastFileCleaner(); long delay = Instant.now().toEpochMilli() - TimeUnit.MINUTES.toMillis(2); logger.log(LogLevel.INFO, FILE_CLEANER_INVOKED_INITIATING_TEMP_FILE_DIRECTORY_CLEANUP, FileCleaner.class.getName()); FileUtils.iterateFiles(new File(osVariables.getTmpDirectory()), new AgeFileFilter(delay), DirectoryFileFilter.INSTANCE).forEachRemaining( file -> { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java index d940d5844..3dd718845 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java @@ -45,11 +45,9 @@ private EventSendPool() { protected void afterExecute(Runnable r, Throwable t) { try { if (t != null) { - AgentInfo.getInstance().getJaHealthCheck().incrementDropCount(); - AgentInfo.getInstance().getJaHealthCheck().incrementEventSendErrorCount(); - incrementCount(r, IUtilConstants.ERROR); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementError(); } else { - incrementCount(r, IUtilConstants.SENT); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementCompleted(); } } catch (Throwable ignored){} super.afterExecute(r, t); @@ -86,13 +84,13 @@ public void sendEvent(String event) { } public void sendEvent(JavaAgentEventBean event) { + if(!event.getIsIASTRequest() && !AgentUsageMetric.isRASPProcessingActive()){ - AgentInfo.getInstance().getJaHealthCheck().getRaspEventStats().incrementRejectedCount(); - AgentInfo.getInstance().getJaHealthCheck().incrementEventSendRejectionCount(); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDroppedDueTo().incrementRaspProcessingDeactivated(); return; } executor.submit(new EventSender(event)); - AgentInfo.getInstance().getJaHealthCheck().incrementEventSentCount(); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementSubmitted(); } public void sendEvent(Object event) { @@ -149,18 +147,12 @@ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } else { RestRequestThreadPool.getInstance().getRejectedIds().add(fuzzRequestId); } - AgentInfo.getInstance().getJaHealthCheck().getIastEventStats().incrementRejectedCount(); - } else { - AgentInfo.getInstance().getJaHealthCheck().getRaspEventStats().incrementRejectedCount(); } - } else if (eventSender.getEvent() instanceof ExitEventBean) { - AgentInfo.getInstance().getJaHealthCheck().getExitEventStats().incrementRejectedCount(); } } logger.log(LogLevel.FINER, "Event Send Task " + r.toString() + " rejected from " + e.toString(), EventSendPool.class.getName()); - AgentInfo.getInstance().getJaHealthCheck().incrementDropCount(); - AgentInfo.getInstance().getJaHealthCheck().incrementEventSendRejectionCount(); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementRejected(); } } @@ -172,43 +164,6 @@ public ThreadPoolExecutor getExecutor() { return executor; } - private void incrementCount(Runnable r, String type) { - EventStats eventStats = null; - if (r instanceof CustomFutureTask && ((CustomFutureTask) r).getTask() instanceof EventSender) { - EventSender eventSender = (EventSender) ((CustomFutureTask) r).getTask(); - if (eventSender.getEvent() instanceof JavaAgentEventBean) { - JavaAgentEventBean event = (JavaAgentEventBean) eventSender.getEvent(); - if (event.getIsIASTRequest()) { - eventStats = AgentInfo.getInstance().getJaHealthCheck().getIastEventStats(); - } else { - eventStats = AgentInfo.getInstance().getJaHealthCheck().getRaspEventStats(); - } - } else if (eventSender.getEvent() instanceof ExitEventBean) { - eventStats = AgentInfo.getInstance().getJaHealthCheck().getExitEventStats(); - } - } - - if(eventStats == null){ - return; - } - switch (type){ - case IUtilConstants.ERROR: - eventStats.incrementErrorCount(); - break; - case IUtilConstants.PROCESSED: - eventStats.incrementProcessedCount(); - break; - case IUtilConstants.SENT: - eventStats.incrementSentCount(); - break; - case IUtilConstants.REJECTED: - eventStats.incrementRejectedCount(); - break; - default: - logger.log(LogLevel.FINEST, String.format("Couldn't update event matric for task :%s and type : %s", r, type), EventSendPool.class.getName()); - } - } - public void reset() { executor.getQueue().clear(); } 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 d2f07257d..df8ebdffe 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 @@ -2,7 +2,6 @@ import com.newrelic.agent.security.AgentConfig; 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; @@ -179,6 +178,7 @@ public void openConnection() throws InterruptedException { @Override public void onOpen(ServerHandshake handshakedata) { + AgentInfo.getInstance().getJaHealthCheck().getWebSocketConnectionStats().incrementConnectionReconnected(); logger.logInit(LogLevel.INFO, String.format(IAgentConstants.INIT_WS_CONNECTION, AgentConfig.getInstance().getConfig().getK2ServiceInfo().getValidatorServiceEndpointURL()), WSClient.class.getName()); logger.logInit(LogLevel.INFO, String.format(IAgentConstants.SENDING_APPLICATION_INFO_ON_WS_CONNECT, AgentInfo.getInstance().getApplicationInfo()), WSClient.class.getName()); @@ -200,6 +200,7 @@ public void onOpen(ServerHandshake handshakedata) { public void onMessage(String message) { // Receive communication from IC side. try { + AgentInfo.getInstance().getJaHealthCheck().getWebSocketConnectionStats().incrementMessagesSent(); if (logger.isLogLevelEnabled(LogLevel.FINEST)) { logger.log(LogLevel.FINEST, String.format(INCOMING_CONTROL_COMMAND_S, message), this.getClass().getName()); @@ -226,6 +227,7 @@ public void onClose(int code, String reason, boolean remote) { @Override public void onError(Exception ex) { + AgentInfo.getInstance().getJaHealthCheck().getWebSocketConnectionStats().incrementConnectionFailure(); logger.logInit(LogLevel.SEVERE, String.format(IAgentConstants.WS_CONNECTION_UNSUCCESSFUL_INFO, AgentConfig .getInstance().getConfig().getK2ServiceInfo().getValidatorServiceEndpointURL(), ex.toString(), ex.getCause()), @@ -243,8 +245,10 @@ public void send(String text) { if (this.isOpen()) { logger.log(LogLevel.FINER, SENDING_EVENT + text, WSClient.class.getName()); super.send(text); + AgentInfo.getInstance().getJaHealthCheck().getWebSocketConnectionStats().incrementMessagesSent(); } else { logger.log(LogLevel.FINER, UNABLE_TO_SEND_EVENT + text, WSClient.class.getName()); + AgentInfo.getInstance().getJaHealthCheck().getWebSocketConnectionStats().incrementSendFailure(); } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSReconnectionST.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSReconnectionST.java index bcbbe8945..ce55ac6e2 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSReconnectionST.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/WSReconnectionST.java @@ -1,5 +1,6 @@ package com.newrelic.agent.security.intcodeagent.websocket; +import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; @@ -25,6 +26,7 @@ public class WSReconnectionST { @Override public void run() { try { + AgentInfo.getInstance().getJaHealthCheck().getSchedulerRuns().incrementWebsocketReconnector(); if(!WSClient.getInstance().isOpen() || !WSUtils.isConnected()) { logger.log(LogLevel.INFO, "WS is marked disconnected, reconnecting ...", WSReconnectionST.class.getName()); WSClient.reconnectWSClient(); 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 20251b010..c9dccf1a7 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 @@ -247,6 +247,7 @@ private void deactivateSecurityServices(){ @Override public void registerOperation(AbstractOperation operation) { + AgentInfo.getInstance().getJaHealthCheck().incrementInvokedHookCount(); // added to fetch request/response in case of grpc requests boolean lockAcquired = ThreadLocalLockHelper.acquireLock(); try { @@ -293,6 +294,7 @@ public void registerOperation(AbstractOperation operation) { logger.log(LogLevel.FINEST, DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL + JsonConverter.toJSON(operation), Agent.class.getName()); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDroppedDueTo().getCsecInternalEvent(); return; } @@ -300,6 +302,7 @@ public void registerOperation(AbstractOperation operation) { logger.log(LogLevel.FINEST, DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL + JsonConverter.toJSON(operation), Agent.class.getName()); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDroppedDueTo().getNrInternalEvent(); return; } @@ -519,7 +522,6 @@ public void registerExitEvent(AbstractOperation operation) { exitEventBean.setK2RequestIdentifier(k2RequestIdentifier.getRaw()); logger.log(LogLevel.FINER, "Exit event : " + exitEventBean, this.getClass().getName()); DispatcherPool.getInstance().dispatchExitEvent(exitEventBean); - AgentInfo.getInstance().getJaHealthCheck().incrementExitEventSentCount(); } } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GrpcClientRequestReplayHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GrpcClientRequestReplayHelper.java index 46c0e305d..eb2eef653 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GrpcClientRequestReplayHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GrpcClientRequestReplayHelper.java @@ -93,6 +93,9 @@ public Set getPendingIds() { return pendingIds; } + + + public void registerEventForProcessedCC(String controlCommandId, String eventId) { if(StringUtils.isAnyBlank(controlCommandId, eventId)){ return; From cbb6cbf3f05730c19426d4e6ce8ce470cb543ace Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 12 Jun 2024 09:37:00 +0530 Subject: [PATCH 004/122] Check for request body limit on register event, current limit is 500KB --- .../newrelic/api/agent/security/Agent.java | 25 +++++++++++++++++++ .../agent/security/schema/HttpRequest.java | 5 ++++ 2 files changed, 30 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 20251b010..9cc9d2018 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 @@ -252,6 +252,8 @@ public void registerOperation(AbstractOperation operation) { try { if(lockAcquired) { SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + isRequestBodyDataExccedsAllowedLimit(securityMetaData); + if (securityMetaData != null && securityMetaData.getRequest().getIsGrpc()) { securityMetaData.getRequest().setBody( new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_REQUEST_DATA, List.class)))); @@ -327,6 +329,29 @@ public void registerOperation(AbstractOperation operation) { } } + private static boolean isRequestBodyDataExccedsAllowedLimit(SecurityMetaData securityMetaData) { + if(securityMetaData != null && StringUtils.length(securityMetaData.getRequest().getBody()) > HttpRequest.MAX_ALLOWED_REQUEST_BODY_LENGTH) { + securityMetaData.getRequest().setDataTruncated(true); + securityMetaData.getRequest().setBody(new StringBuilder()); + return true; + //TODO send IASTScanFailure for body truncation and drop event. + } + if(!securityMetaData.getRequest().getParameterMap().isEmpty()) { + boolean parameterTruncated = false; + for (String[] requestParam : securityMetaData.getRequest().getParameterMap().values()) { + if(requestParam.length > HttpRequest.MAX_ALLOWED_REQUEST_BODY_LENGTH) { + securityMetaData.getRequest().setDataTruncated(true); + parameterTruncated = true; + } + } + if(parameterTruncated) { + securityMetaData.getRequest().getParameterMap().clear(); + } + return true; + } + return false; + } + 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. diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java index 0c19eac73..ad734aee0 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java @@ -1,11 +1,16 @@ package com.newrelic.api.agent.security.schema; +import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; + import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class HttpRequest { public static final String HTTP = "http"; + @JsonIgnore + public static final int MAX_ALLOWED_REQUEST_BODY_LENGTH = 500000; + private StringBuilder body; private boolean dataTruncated; From 07cdfbd574ffa115d1cbb5275b00b82169bdb760 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 12 Jun 2024 14:00:15 +0530 Subject: [PATCH 005/122] Upgrade Log file size and count handling --- .../filelogging/FileLoggerThreadPool.java | 6 +++--- .../filelogging/InitLogWriter.java | 4 +++- .../filelogging/LogFileHelper.java | 18 +++++++++++++----- .../intcodeagent/filelogging/LogWriter.java | 4 +++- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java index 521f4cd75..55ea39e46 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java @@ -20,7 +20,7 @@ public class FileLoggerThreadPool { private boolean isInitLoggingActive = true; - protected final int maxfilesize; + protected final long maxfilesize; protected final int maxfiles; @@ -32,8 +32,8 @@ private FileLoggerThreadPool() throws IOException { int maxPoolSize = 1; int corePoolSize = 1; long keepAliveTime = 600; - maxfiles = Math.max(K2JALogProperties.maxfiles, LogFileHelper.logFileCount()); - maxfilesize = LogFileHelper.logFileLimit()*1024; + maxfiles = LogFileHelper.logFileCount(); + maxfilesize = LogFileHelper.logFileLimit()* 1024L; TimeUnit timeUnit = TimeUnit.SECONDS; 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 ba49ac376..ed8876f7c 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 @@ -178,7 +178,9 @@ public void run() { FileLoggerThreadPool.getInstance().setInitLoggingActive(true); // writer.newLine(); - rollover(currentLogFileName); + if(maxFileSize > 0) { + rollover(currentLogFileName); + } } catch (IOException e) { //TODO report to cloud FileLoggerThreadPool.getInstance().setInitLoggingActive(false); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogFileHelper.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogFileHelper.java index 196dba274..4cc1901ce 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogFileHelper.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/LogFileHelper.java @@ -37,12 +37,13 @@ public class LogFileHelper { public static final String LOG_LIMIT = "log_limit_in_kbytes"; public static final boolean DEFAULT_LOG_DAILY = false; - public static final int DEFAULT_LOG_FILE_COUNT = 1; + public static final Integer DEFAULT_LOG_FILE_COUNT = 1; public static final String DEFAULT_LOG_FILE_NAME = "java-security-collector.log"; public static final String STDOUT = "STDOUT"; private static final String STRING_DOT = "."; + private static final Integer DEFAULT_LOG_FILE_LIMIT = 0; public static boolean isLoggingToStdOut() { String logFileName = NewRelic.getAgent().getConfig().getValue(LogFileHelper.LOG_FILE_NAME, LogFileHelper.DEFAULT_LOG_FILE_NAME); @@ -50,19 +51,26 @@ public static boolean isLoggingToStdOut() { } public static int logFileCount() { - return Math.max(1, NewRelic.getAgent().getConfig().getValue(LogFileHelper.LOG_FILE_COUNT, LogFileHelper.DEFAULT_LOG_FILE_COUNT)); + try { + return NewRelic.getAgent().getConfig().getValue(LogFileHelper.LOG_FILE_COUNT, LogFileHelper.DEFAULT_LOG_FILE_COUNT); + } catch (Exception e) { + return LogFileHelper.DEFAULT_LOG_FILE_COUNT; + } } public static int logFileLimit() { - int size = NewRelic.getAgent().getConfig().getValue(LogFileHelper.LOG_LIMIT, 1); - return size>1?size: K2JALogProperties.maxfilesize; + try { + return NewRelic.getAgent().getConfig().getValue(LogFileHelper.LOG_LIMIT, DEFAULT_LOG_FILE_LIMIT); + } catch (Exception e) { + return DEFAULT_LOG_FILE_LIMIT; + } } public static boolean isDailyRollover() { return NewRelic.getAgent().getConfig().getValue(LogFileHelper.LOG_DAILY, LogFileHelper.DEFAULT_LOG_DAILY); } - public static void deleteRolloverLogFiles(String fileName, int max) { + public static void deleteRolloverLogFiles(String fileName, long max) { Collection rolloverLogFiles = FileUtils.listFiles(new File(OsVariablesInstance.getInstance().getOsVariables().getLogDirectory()), FileFilterUtils.prefixFileFilter(fileName + "."), null); if (rolloverLogFiles.size() > max) { 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 1fac40082..e4f8c9258 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 @@ -178,7 +178,9 @@ public void run() { FileLoggerThreadPool.getInstance().setLoggingActive(true); // writer.newLine(); - rollover(currentLogFileName); + if(maxFileSize > 0){ + rollover(currentLogFileName); + } } catch (IOException e) { if (FileLoggerThreadPool.getInstance().isLoggingActive()) { //TODO report to cloud From ef7c245c18a09a558d06e0bc42df6c8471c3b2b4 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 12 Jun 2024 17:21:29 +0530 Subject: [PATCH 006/122] Update and add unit tests for secure cookie instrumentation support --- .../servlet24/HttpSessionTest.java | 149 +++++++++++++---- .../servlet24/HttpTestServlet.java | 30 +++- .../servlet5/HttpSessionTest.java | 151 ++++++++++++++---- .../servlet5/HttpTestServlet.java | 32 +++- .../servlet6/HttpSessionTest.java | 145 +++++++++++++---- .../servlet6/HttpTestServlet.java | 34 +++- 6 files changed, 443 insertions(+), 98 deletions(-) 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 83fb8f15d..1902c87c8 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 @@ -18,6 +18,7 @@ import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; +import java.util.Iterator; import java.util.List; @RunWith(SecurityInstrumentationTestRunner.class) @@ -29,9 +30,7 @@ public class HttpSessionTest { @Test public void testSessionSetAttribute() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "set"); + makeRequest("set"); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); @@ -61,9 +60,7 @@ else if(i==1){ @Test public void testSessionPutValue() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "put"); + makeRequest("put"); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); @@ -84,49 +81,117 @@ public void testSessionPutValue() throws IOException, URISyntaxException { @Test public void testAddCookie() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "cookie"); + makeRequest("securecookie"); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); Assert.assertTrue("No operations detected", operations.size() > 0); Assert.assertTrue("Unexpected operation count detected", operations.size() == 1 || operations.size() == 2); SecureCookieOperationSet targetOperation = null; - for (AbstractOperation operation : operations) { - if (operation instanceof SecureCookieOperationSet) - targetOperation = (SecureCookieOperationSet) operation; - }; - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.SECURE_COOKIE, targetOperation.getCaseType()); - Assert.assertEquals("Wrong key detected", "false", targetOperation.getValue()); + targetOperation = verifySecureCookieOp(operations); + + Assert.assertEquals(1, targetOperation.getOperations().size()); + Iterator secureCookieOps = targetOperation.getOperations().iterator(); + Assert.assertTrue(secureCookieOps.hasNext()); + + SecureCookieOperationSet.SecureCookieOperation secureCookieOp = secureCookieOps.next(); + verifySecureCookie(secureCookieOp, "key", false, true); } @Test public void testAddCookie1() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "securecookie"); + makeRequest("cookie"); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); - Assert.assertTrue("Unexpected operation count detected", operations.size() == 1 || operations.size() == 2); - SecureCookieOperationSet targetOperation = null; - for (AbstractOperation operation : operations) { - if (operation instanceof SecureCookieOperationSet) - targetOperation = (SecureCookieOperationSet) operation; - }; - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.SECURE_COOKIE, targetOperation.getCaseType()); - Assert.assertEquals("Wrong key detected", "true", targetOperation.getValue()); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(1, targetOperation.getOperations().size()); + + Iterator secureCookieOps = targetOperation.getOperations().iterator(); + Assert.assertTrue(secureCookieOps.hasNext()); + + SecureCookieOperationSet.SecureCookieOperation secureCookieOp = secureCookieOps.next(); + verifySecureCookie(secureCookieOp, "key", false, false); } - private void makeRequest( String Method, final String POST_PARAMS, String path) throws URISyntaxException, IOException{ + @Test + public void testAddSecureCookies() throws IOException, URISyntaxException { + makeRequest("secure_cookies"); + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(2, targetOperation.getOperations().size()); + + for (SecureCookieOperationSet.SecureCookieOperation secureCookieOp : targetOperation.getOperations()) { + if (secureCookieOp.getName().equals("secure-cookie-1")) { + verifySecureCookie(secureCookieOp, "secure-cookie-1", false, true); + } else { + verifySecureCookie(secureCookieOp, "secure-cookie-2", true, true); + } + } + } + + @Test + public void testAddInSecureCookies() throws IOException, URISyntaxException { + makeRequest("insecure_cookies"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(2, targetOperation.getOperations().size()); + + for (SecureCookieOperationSet.SecureCookieOperation secureCookieOp : targetOperation.getOperations()) { + if (secureCookieOp.getName().equals("insecure-cookie-1")) { + verifySecureCookie(secureCookieOp, "insecure-cookie-1", false, false); + } else { + verifySecureCookie(secureCookieOp, "insecure-cookie-2", false, false); + } + } + } + + @Test + public void testAddMultiSecureCookies() throws IOException, URISyntaxException { + makeRequest("cookies"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(2, targetOperation.getOperations().size()); + + for (SecureCookieOperationSet.SecureCookieOperation secureCookieOp : targetOperation.getOperations()) { + if (secureCookieOp.getName().equals("insecure-cookie")) { + verifySecureCookie(secureCookieOp, "insecure-cookie", false, false); + } else { + verifySecureCookie(secureCookieOp, "secure-cookie", false, true); + } + } + } + + @Test + public void testSingleCookie() throws IOException, URISyntaxException { + makeRequest("single-cookie"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(1, targetOperation.getOperations().size()); + + Iterator secureCookieOps = targetOperation.getOperations().iterator(); + + Assert.assertTrue(secureCookieOps.hasNext()); + SecureCookieOperationSet.SecureCookieOperation secureCookieOp = secureCookieOps.next(); + verifySecureCookie(secureCookieOp, "cookie", true, true); + } + + private void makeRequest(String path) throws URISyntaxException, IOException{ URL u = server.getEndPoint("session/"+path).toURL(); HttpURLConnection conn = (HttpURLConnection) u.openConnection(); - conn.setRequestMethod(Method); conn.setDoOutput(true); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Cache-Control", "no-cache"); @@ -134,6 +199,28 @@ private void makeRequest( String Method, final String POST_PARAMS, String path) conn.connect(); conn.getResponseCode(); + } + + private SecureCookieOperationSet verifySecureCookieOp(List operations) { + SecureCookieOperationSet targetOperation = null; + for (AbstractOperation operation : operations) { + if (operation instanceof SecureCookieOperationSet) { + targetOperation = (SecureCookieOperationSet) operation; + } + } + + Assert.assertNotNull("No target operation detected", targetOperation); + Assert.assertEquals("Wrong method detected", "addCookie", targetOperation.getMethodName()); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.SECURE_COOKIE, targetOperation.getCaseType()); + Assert.assertTrue("isLowSeverityHook should be true", targetOperation.isLowSeverityHook()); + return targetOperation; + } + private void verifySecureCookie(SecureCookieOperationSet.SecureCookieOperation secureCookieOp, String key, boolean isHttpOnly, boolean isSecure) { + Assert.assertEquals("Wrong cookie key detected", key, secureCookieOp.getName()); + Assert.assertEquals("Wrong cookie value detected", "value", secureCookieOp.getValue()); + Assert.assertEquals(String.format("isHttpOnly should be %s", isHttpOnly), isHttpOnly, secureCookieOp.isHttpOnly()); + Assert.assertEquals(String.format("isSecure should be %s", isSecure), isSecure, secureCookieOp.isSecure()); + Assert.assertTrue(String.format("isSameSiteStrict should be %s", true), secureCookieOp.isSameSiteStrict()); } } diff --git a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpTestServlet.java b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpTestServlet.java index 896b24d07..2e53978e0 100644 --- a/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpTestServlet.java +++ b/instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpTestServlet.java @@ -102,7 +102,35 @@ else if(path.equals("/session/put")){ cookie.setSecure(true); response.addCookie(cookie); } else if(path.equals("/session/cookie")){ - Cookie cookie = new Cookie("key1", "value1"); + // add insecure cookie to response + response.addCookie(new Cookie("key", "value")); + } else if (path.equals("/session/secure_cookies")) { + // add multiple secure cookies to response + Cookie cookie = new Cookie("secure-cookie-1", "value"); + cookie.setSecure(true); + response.addCookie(cookie); + + Cookie cookie1 = new Cookie("secure-cookie-2", "value"); + cookie1.setSecure(true); + cookie1.setHttpOnly(true); + cookie1.setComment("__SAME_SITE_STRICT__"); + response.addCookie(cookie1); + } else if (path.equals("/session/insecure_cookies")) { + // add multiple insecure cookies to response + response.addCookie(new Cookie("insecure-cookie-1", "value")); + response.addCookie(new Cookie("insecure-cookie-2", "value")); + } else if (path.equals("/session/cookies")){ + // add multiple cookies to response + Cookie cookie = new Cookie("secure-cookie", "value"); + cookie.setSecure(true); + response.addCookie(cookie); + + response.addCookie(new Cookie("insecure-cookie","value")); + } else if (path.equals("/session/single-cookie")){ + Cookie cookie = new Cookie("cookie", "value"); + cookie.setSecure(true); + cookie.setHttpOnly(true); + cookie.setComment("__SAME_SITE_LAX__"); response.addCookie(cookie); } } diff --git a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpSessionTest.java b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpSessionTest.java index a7a00714b..f39ae8fa0 100644 --- a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpSessionTest.java +++ b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpSessionTest.java @@ -18,6 +18,7 @@ import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; +import java.util.Iterator; import java.util.List; @RunWith(SecurityInstrumentationTestRunner.class) @@ -29,9 +30,7 @@ public class HttpSessionTest { @Test public void testSessionSetAttribute() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "set"); + makeRequest("set"); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); @@ -61,9 +60,7 @@ else if(i==1){ @Test public void testSessionPutValue() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "put"); + makeRequest("put"); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); @@ -79,53 +76,122 @@ public void testSessionPutValue() throws IOException, URISyntaxException { Assert.assertEquals("Wrong key detected", "key1", targetOperation.getKey()); Assert.assertEquals("Wrong value detected", "value1", targetOperation.getValue()); } + } @Test public void testAddCookie() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "cookie"); + makeRequest("securecookie"); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); Assert.assertTrue("No operations detected", operations.size() > 0); Assert.assertTrue("Unexpected operation count detected", operations.size() == 1 || operations.size() == 2); SecureCookieOperationSet targetOperation = null; - for (AbstractOperation operation : operations) { - if (operation instanceof SecureCookieOperationSet) - targetOperation = (SecureCookieOperationSet) operation; - }; - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.SECURE_COOKIE, targetOperation.getCaseType()); - Assert.assertEquals("Wrong key detected", "false", targetOperation.getValue()); + targetOperation = verifySecureCookieOp(operations); + + Assert.assertEquals(1, targetOperation.getOperations().size()); + Iterator secureCookieOps = targetOperation.getOperations().iterator(); + Assert.assertTrue(secureCookieOps.hasNext()); + + SecureCookieOperationSet.SecureCookieOperation secureCookieOp = secureCookieOps.next(); + verifySecureCookie(secureCookieOp, "key", false, true); } @Test public void testAddCookie1() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "securecookie"); + makeRequest("cookie"); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); - Assert.assertTrue("No operations detected", operations.size() > 0); - Assert.assertTrue("Unexpected operation count detected", operations.size() == 1 || operations.size() == 2); - SecureCookieOperationSet targetOperation = null; - for (AbstractOperation operation : operations) { - if (operation instanceof SecureCookieOperationSet) - targetOperation = (SecureCookieOperationSet) operation; - }; - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.SECURE_COOKIE, targetOperation.getCaseType()); - Assert.assertEquals("Wrong key detected", "true", targetOperation.getValue()); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(1, targetOperation.getOperations().size()); + + Iterator secureCookieOps = targetOperation.getOperations().iterator(); + Assert.assertTrue(secureCookieOps.hasNext()); + + SecureCookieOperationSet.SecureCookieOperation secureCookieOp = secureCookieOps.next(); + verifySecureCookie(secureCookieOp, "key", false, false); } - private void makeRequest( String Method, final String POST_PARAMS, String path) throws URISyntaxException, IOException{ + @Test + public void testAddSecureCookies() throws IOException, URISyntaxException { + makeRequest("secure_cookies"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(2, targetOperation.getOperations().size()); + + for (SecureCookieOperationSet.SecureCookieOperation secureCookieOp : targetOperation.getOperations()) { + if (secureCookieOp.getName().equals("secure-cookie-1")) { + verifySecureCookie(secureCookieOp, "secure-cookie-1", false, true); + } else { + verifySecureCookie(secureCookieOp, "secure-cookie-2", true, true); + } + } + } + @Test + public void testAddInSecureCookies() throws IOException, URISyntaxException { + makeRequest("insecure_cookies"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(2, targetOperation.getOperations().size()); + + for (SecureCookieOperationSet.SecureCookieOperation secureCookieOp : targetOperation.getOperations()) { + if (secureCookieOp.getName().equals("insecure-cookie-1")) { + verifySecureCookie(secureCookieOp, "insecure-cookie-1", false, false); + } else { + verifySecureCookie(secureCookieOp, "insecure-cookie-2", false, false); + } + } + } + + @Test + public void testAddMultiSecureCookies() throws IOException, URISyntaxException { + makeRequest("cookies"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(2, targetOperation.getOperations().size()); + + for (SecureCookieOperationSet.SecureCookieOperation secureCookieOp : targetOperation.getOperations()) { + if (secureCookieOp.getName().equals("insecure-cookie")) { + verifySecureCookie(secureCookieOp, "insecure-cookie", false, false); + } else { + verifySecureCookie(secureCookieOp, "secure-cookie", false, true); + } + } + } + + @Test + public void testSingleCookie() throws IOException, URISyntaxException { + makeRequest("single-cookie"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(1, targetOperation.getOperations().size()); + + Iterator secureCookieOps = targetOperation.getOperations().iterator(); + + Assert.assertTrue(secureCookieOps.hasNext()); + SecureCookieOperationSet.SecureCookieOperation secureCookieOp = secureCookieOps.next(); + verifySecureCookie(secureCookieOp, "cookie", true, true); + } + + private void makeRequest(String path) throws URISyntaxException, IOException{ URL u = server.getEndPoint("session/"+path).toURL(); HttpURLConnection conn = (HttpURLConnection) u.openConnection(); - conn.setRequestMethod(Method); conn.setDoOutput(true); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Cache-Control", "no-cache"); @@ -133,6 +199,29 @@ private void makeRequest( String Method, final String POST_PARAMS, String path) conn.connect(); conn.getResponseCode(); + } + + private SecureCookieOperationSet verifySecureCookieOp(List operations) { + SecureCookieOperationSet targetOperation = null; + for (AbstractOperation operation : operations) { + if (operation instanceof SecureCookieOperationSet) { + targetOperation = (SecureCookieOperationSet) operation; + } + } + + Assert.assertNotNull("No target operation detected", targetOperation); + Assert.assertEquals("Wrong method detected", "addCookie", targetOperation.getMethodName()); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.SECURE_COOKIE, targetOperation.getCaseType()); + Assert.assertTrue("isLowSeverityHook should be true", targetOperation.isLowSeverityHook()); + return targetOperation; + } + private void verifySecureCookie(SecureCookieOperationSet.SecureCookieOperation secureCookieOp, String key, boolean isHttpOnly, boolean isSecure) { + Assert.assertEquals("Wrong cookie key detected", key, secureCookieOp.getName()); + Assert.assertEquals("Wrong cookie value detected", "value", secureCookieOp.getValue()); + Assert.assertEquals(String.format("isHttpOnly should be %s", isHttpOnly), isHttpOnly, secureCookieOp.isHttpOnly()); + Assert.assertEquals(String.format("isSecure should be %s", isSecure), isSecure, secureCookieOp.isSecure()); + Assert.assertTrue(String.format("isSameSiteStrict should be %s", true), secureCookieOp.isSameSiteStrict()); } + } diff --git a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpTestServlet.java b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpTestServlet.java index 89df822d9..e0b0611fd 100644 --- a/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpTestServlet.java +++ b/instrumentation-security/servlet-5.0/src/test/java/com/nr/agent/security/instrumentation/servlet5/HttpTestServlet.java @@ -103,8 +103,36 @@ else if(path.equals("/session/securecookie")){ Cookie cookie = new Cookie("key", "value"); cookie.setSecure(true); response.addCookie(cookie); - } else if(path.equals("/session/cookie")){ - Cookie cookie = new Cookie("key1", "value1"); + } else if(path.equals("/session/cookie")){ + // add insecure cookie to response + response.addCookie(new Cookie("key", "value")); + } else if (path.equals("/session/secure_cookies")) { + // add multiple secure cookies to response + Cookie cookie = new Cookie("secure-cookie-1", "value"); + cookie.setSecure(true); + response.addCookie(cookie); + + Cookie cookie1 = new Cookie("secure-cookie-2", "value"); + cookie1.setSecure(true); + cookie1.setHttpOnly(true); + cookie1.setComment("__SAME_SITE_STRICT__"); + response.addCookie(cookie1); + } else if (path.equals("/session/insecure_cookies")) { + // add multiple insecure cookies to response + response.addCookie(new Cookie("insecure-cookie-1", "value")); + response.addCookie(new Cookie("insecure-cookie-2", "value")); + } else if (path.equals("/session/cookies")){ + // add multiple cookies to response + Cookie cookie = new Cookie("secure-cookie", "value"); + cookie.setSecure(true); + response.addCookie(cookie); + + response.addCookie(new Cookie("insecure-cookie","value")); + } else if (path.equals("/session/single-cookie")){ + Cookie cookie = new Cookie("cookie", "value"); + cookie.setSecure(true); + cookie.setHttpOnly(true); + cookie.setComment("__SAME_SITE_LAX__"); response.addCookie(cookie); } } diff --git a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpSessionTest.java b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpSessionTest.java index 15dec1fa9..5896fbdf2 100644 --- a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpSessionTest.java +++ b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpSessionTest.java @@ -18,6 +18,7 @@ import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; +import java.util.Iterator; import java.util.List; @RunWith(SecurityInstrumentationTestRunner.class) @@ -29,9 +30,7 @@ public class HttpSessionTest { @Test public void testSessionSetAttribute() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "session"); + makeRequest(""); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); @@ -61,49 +60,116 @@ else if(i==1){ @Test public void testAddCookie() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "cookie"); + makeRequest("/cookie"); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); Assert.assertTrue("No operations detected", operations.size() > 0); Assert.assertTrue("Unexpected operation count detected", operations.size() == 1 || operations.size() == 2); - SecureCookieOperationSet targetOperation = null; - for (AbstractOperation operation : operations) { - if (operation instanceof SecureCookieOperationSet) - targetOperation = (SecureCookieOperationSet) operation; - }; - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.SECURE_COOKIE, targetOperation.getCaseType()); - Assert.assertEquals("Wrong key detected", "false", targetOperation.getValue()); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Iterator secureCookieOps = targetOperation.getOperations().iterator(); + Assert.assertTrue(secureCookieOps.hasNext()); + + SecureCookieOperationSet.SecureCookieOperation secureCookieOp = secureCookieOps.next(); + verifySecureCookie(secureCookieOp, "key", false, false); } @Test public void testAddCookie1() throws IOException, URISyntaxException { - String method = "GET"; - String POST_PARAMS = "hook=readLine"; - makeRequest(method, POST_PARAMS, "securecookie"); + makeRequest("/securecookie"); SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); List operations = introspector.getOperations(); Assert.assertTrue("No operations detected", operations.size() > 0); Assert.assertTrue("Unexpected operation count detected", operations.size() == 1 || operations.size() == 2); - SecureCookieOperationSet targetOperation = null; - for (AbstractOperation operation : operations) { - if (operation instanceof SecureCookieOperationSet) - targetOperation = (SecureCookieOperationSet) operation; - }; - Assert.assertNotNull("No target operation detected", targetOperation); - Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.SECURE_COOKIE, targetOperation.getCaseType()); - Assert.assertEquals("Wrong key detected", "true", targetOperation.getValue()); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + + Iterator secureCookieOps = targetOperation.getOperations().iterator(); + Assert.assertTrue(secureCookieOps.hasNext()); + + SecureCookieOperationSet.SecureCookieOperation secureCookieOp = secureCookieOps.next(); + verifySecureCookie(secureCookieOp, "key", false, true); + } + + @Test + public void testAddSecureCookies() throws IOException, URISyntaxException { + makeRequest("/secure_cookies"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(2, targetOperation.getOperations().size()); + + for (SecureCookieOperationSet.SecureCookieOperation secureCookieOp : targetOperation.getOperations()) { + if (secureCookieOp.getName().equals("secure-cookie-1")) { + verifySecureCookie(secureCookieOp, "secure-cookie-1", false, true); + } else { + verifySecureCookie(secureCookieOp, "secure-cookie-2", true, true); + } + } } - private void makeRequest( String Method, final String POST_PARAMS, String path) throws URISyntaxException, IOException{ + @Test + public void testAddInSecureCookies() throws IOException, URISyntaxException { + makeRequest("/insecure_cookies"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(2, targetOperation.getOperations().size()); - URL u = server.getEndPoint(path).toURL(); + for (SecureCookieOperationSet.SecureCookieOperation secureCookieOp : targetOperation.getOperations()) { + if (secureCookieOp.getName().equals("insecure-cookie-1")) { + verifySecureCookie(secureCookieOp, "insecure-cookie-1", false, false); + } else { + verifySecureCookie(secureCookieOp, "insecure-cookie-2", false, false); + } + } + } + + @Test + public void testAddMultiSecureCookies() throws IOException, URISyntaxException { + makeRequest("/cookies"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(2, targetOperation.getOperations().size()); + + for (SecureCookieOperationSet.SecureCookieOperation secureCookieOp : targetOperation.getOperations()) { + if (secureCookieOp.getName().equals("insecure-cookie")) { + verifySecureCookie(secureCookieOp, "insecure-cookie", false, false); + } else { + verifySecureCookie(secureCookieOp, "secure-cookie", false, true); + } + } + } + + @Test + public void testSingleCookie() throws IOException, URISyntaxException { + makeRequest("/single-cookie"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + List operations = introspector.getOperations(); + + SecureCookieOperationSet targetOperation = verifySecureCookieOp(operations); + Assert.assertEquals(1, targetOperation.getOperations().size()); + + Iterator secureCookieOps = targetOperation.getOperations().iterator(); + + Assert.assertTrue(secureCookieOps.hasNext()); + SecureCookieOperationSet.SecureCookieOperation secureCookieOp = secureCookieOps.next(); + verifySecureCookie(secureCookieOp, "cookie", true, true); + } + + private void makeRequest(String path) throws URISyntaxException, IOException{ + URL u = server.getEndPoint("session"+path).toURL(); HttpURLConnection conn = (HttpURLConnection) u.openConnection(); - conn.setRequestMethod(Method); conn.setDoOutput(true); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Cache-Control", "no-cache"); @@ -111,6 +177,27 @@ private void makeRequest( String Method, final String POST_PARAMS, String path) conn.connect(); conn.getResponseCode(); + } + private SecureCookieOperationSet verifySecureCookieOp(List operations) { + SecureCookieOperationSet targetOperation = null; + for (AbstractOperation operation : operations) { + if (operation instanceof SecureCookieOperationSet) { + targetOperation = (SecureCookieOperationSet) operation; + } + } + + Assert.assertNotNull("No target operation detected", targetOperation); + Assert.assertEquals("Wrong method detected", "addCookie", targetOperation.getMethodName()); + Assert.assertEquals("Wrong case-type detected", VulnerabilityCaseType.SECURE_COOKIE, targetOperation.getCaseType()); + Assert.assertTrue("isLowSeverityHook should be true", targetOperation.isLowSeverityHook()); + return targetOperation; } -} + + private void verifySecureCookie(SecureCookieOperationSet.SecureCookieOperation secureCookieOp, String key, boolean isHttpOnly, boolean isSecure) { + Assert.assertEquals("Wrong cookie key detected", key, secureCookieOp.getName()); + Assert.assertEquals("Wrong cookie value detected", "value", secureCookieOp.getValue()); + Assert.assertEquals(String.format("isHttpOnly should be %s", isHttpOnly), isHttpOnly, secureCookieOp.isHttpOnly()); + Assert.assertEquals(String.format("isSecure should be %s", isSecure), isSecure, secureCookieOp.isSecure()); + Assert.assertTrue(String.format("isSameSiteStrict should be %s", true), secureCookieOp.isSameSiteStrict()); + }} diff --git a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpTestServlet.java b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpTestServlet.java index 098ffed0a..688b00001 100644 --- a/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpTestServlet.java +++ b/instrumentation-security/servlet-6.0/src/test/java/com/nr/agent/security/instrumentation/servlet6/HttpTestServlet.java @@ -94,14 +94,40 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro if(path.equals("/session")){ HttpSession session = request.getSession(true); session.setAttribute("key", "value"); - } else if(path.equals("/securecookie")){ + } else if(path.equals("/session/securecookie")){ Cookie cookie = new Cookie("key", "value"); cookie.setSecure(true); response.addCookie(cookie); - } else if(path.equals("/cookie")){ - Cookie cookie = new Cookie("key", "value"); + } else if(path.equals("/session/cookie")){ + // add insecure cookie to response + response.addCookie(new Cookie("key", "value")); + } else if (path.equals("/session/secure_cookies")) { + // add multiple secure cookies to response + Cookie cookie = new Cookie("secure-cookie-1", "value"); + cookie.setSecure(true); response.addCookie(cookie); - } + + Cookie cookie1 = new Cookie("secure-cookie-2", "value"); + cookie1.setSecure(true); + cookie1.setHttpOnly(true); + response.addCookie(cookie1); + } else if (path.equals("/session/insecure_cookies")) { + // add multiple insecure cookies to response + response.addCookie(new Cookie("insecure-cookie-1", "value")); + response.addCookie(new Cookie("insecure-cookie-2", "value")); + } else if (path.equals("/session/cookies")){ + // add multiple cookies to response + Cookie cookie = new Cookie("secure-cookie", "value"); + cookie.setSecure(true); + response.addCookie(cookie); + + response.addCookie(new Cookie("insecure-cookie","value")); + } else if (path.equals("/session/single-cookie")){ + Cookie cookie = new Cookie("cookie", "value"); + cookie.setSecure(true); + cookie.setHttpOnly(true); + response.addCookie(cookie); + } } private void testServletRequestHooks( HttpServletRequest request, HttpServletResponse response) throws IOException { From 320a4ace251918d52f0ba2c907b64288841a6156 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 20 Jun 2024 11:19:17 +0530 Subject: [PATCH 007/122] Update fuzz header parsing minimum expected length is 8 --- .../helpers/ServletHelper.java | 78 ++++++++++--------- 1 file changed, 40 insertions(+), 38 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 0a8e7d99d..3d6b48b33 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 @@ -80,19 +80,17 @@ public static K2RequestIdentifier parseFuzzRequestIdentifierHeader(String reques && NewRelicSecurity.getAgent().getCurrentPolicy().getVulnerabilityScan().getIastScan().getEnabled())) { return k2RequestIdentifierInstance; } - String[] data = StringUtils.splitByWholeSeparatorWorker(requestHeaderVal, SEPARATOR_SEMICOLON, -1, false); + String[] data = StringUtils.splitByWholeSeparatorWorker(requestHeaderVal, SEPARATOR_SEMICOLON, -1, true); - if (data.length >= 5) { + if (data.length >= 8) { k2RequestIdentifierInstance.setApiRecordId(data[0].trim()); k2RequestIdentifierInstance.setRefId(data[1].trim()); k2RequestIdentifierInstance.setRefValue(data[2].trim()); k2RequestIdentifierInstance.setNextStage(APIRecordStatus.valueOf(data[3].trim())); k2RequestIdentifierInstance.setRecordIndex(Integer.parseInt(data[4].trim())); k2RequestIdentifierInstance.setK2Request(true); - if (data.length >= 6 && StringUtils.isNotBlank(data[5])) { - k2RequestIdentifierInstance.setRefKey(data[5].trim()); - } - if (data.length >= 8) { + k2RequestIdentifierInstance.setRefKey(data[5].trim()); + if(!StringUtils.isAnyBlank(data[6], data[7])) { String encryptedData = data[6].trim(); String hashVerifier = data[7].trim(); String filesToCreate = NewRelicSecurity.getAgent().decryptAndVerify(encryptedData, hashVerifier); @@ -101,44 +99,48 @@ public static K2RequestIdentifier parseFuzzRequestIdentifierHeader(String reques return k2RequestIdentifierInstance; } - String[] allFiles = StringUtils.splitByWholeSeparatorWorker(filesToCreate, StringUtils.COMMA_DELIMETER, -1, false); + fileCreationForReplayRequest(filesToCreate, k2RequestIdentifierInstance); + } + } + } + return k2RequestIdentifierInstance; + } - for (int i = 0; i < allFiles.length; i++) { - String tmpFile = allFiles[i].trim(); - if(StringUtils.contains(tmpFile, NR_CSEC_VALIDATOR_HOME_TMP_URL_ENCODED)) { - tmpFile = urlDecode(tmpFile); - } - tmpFile = StringUtils.replace(tmpFile, NR_CSEC_VALIDATOR_HOME_TMP, - NewRelicSecurity.getAgent().getAgentTempDir()); - k2RequestIdentifierInstance.getTempFiles().add(tmpFile); - boolean lockAcquired = ThreadLocalLockHelper.acquireLock(); - try { - 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()); - } - } - } 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(); + private static void fileCreationForReplayRequest(String filesToCreate, K2RequestIdentifier k2RequestIdentifierInstance) { + String[] allFiles = StringUtils.splitByWholeSeparatorWorker(filesToCreate, StringUtils.COMMA_DELIMETER, -1, false); + + for (int i = 0; i < allFiles.length; i++) { + String tmpFile = allFiles[i].trim(); + if (StringUtils.contains(tmpFile, NR_CSEC_VALIDATOR_HOME_TMP_URL_ENCODED)) { + tmpFile = urlDecode(tmpFile); + } + tmpFile = StringUtils.replace(tmpFile, NR_CSEC_VALIDATOR_HOME_TMP, + NewRelicSecurity.getAgent().getAgentTempDir()); + k2RequestIdentifierInstance.getTempFiles().add(tmpFile); + boolean lockAcquired = ThreadLocalLockHelper.acquireLock(); + try { + 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()); } } + } 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(); } } - return k2RequestIdentifierInstance; } /** From fc83f8429bafd93c3cd20cb4eaac5870a108d9e7 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 2 Jul 2024 10:56:42 +0530 Subject: [PATCH 008/122] Remove use for class.forName, instead use the class of object itself --- .../jersey2/HttpRequestHelper.java | 44 +++++-------------- .../jersey2/HttpRequestHelper.java | 42 +++++------------- .../jersey2/HttpRequestHelper.java | 42 +++++------------- 3 files changed, 32 insertions(+), 96 deletions(-) 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 13be4a980..247508404 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 @@ -13,6 +13,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 jdk.nashorn.internal.codegen.CompilerConstants; import org.glassfish.jersey.internal.PropertiesDelegate; import org.glassfish.jersey.message.internal.OutboundMessageContext; import org.glassfish.jersey.server.ContainerRequest; @@ -230,22 +231,23 @@ private static String getNrSecCustomAttribName() { public static void processPropertiesDelegate(PropertiesDelegate propertiesDelegate, HttpRequest securityRequest) { if(StringUtils.equals(propertiesDelegate.getClass().getName(), ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_GRIZZLY_REQUEST_PROPERTIES_DELEGATE)){ try { - Class grizzlyRequestPropertiesDelegateKlass = getClass(GRIZZLY_REQUEST_PROPERTIES_DELEGATE); + Class grizzlyRequestPropertiesDelegateKlass = propertiesDelegate.getClass(); Field requestField = grizzlyRequestPropertiesDelegateKlass.getDeclaredField(FIELD_REQUEST); requestField.setAccessible(true); Object requestObject = requestField.get(propertiesDelegate); - Class requestClass = getClass(GRIZZLY_REQUEST); - Method getRemoteAddr = requestClass.getDeclaredMethod(METHOD_GET_REMOTE_ADDR); - Method getRemotePort = requestClass.getDeclaredMethod(METHOD_GET_REMOTE_PORT); - Method getLocalPort = requestClass.getDeclaredMethod(METHOD_GET_LOCAL_PORT); - Method getScheme = requestClass.getDeclaredMethod(METHOD_GET_SCHEME); - Method getContentType = requestClass.getDeclaredMethod(METHOD_GET_CONTENT_TYPE); + Class requestClass = requestObject.getClass(); + Method getRemoteAddr = requestClass.getMethod(METHOD_GET_REMOTE_ADDR); + Method getRemotePort = requestClass.getMethod(METHOD_GET_REMOTE_PORT); + Method getLocalPort = requestClass.getMethod(METHOD_GET_LOCAL_PORT); + Method getScheme = requestClass.getMethod(METHOD_GET_SCHEME); + Method getContentType = requestClass.getMethod(METHOD_GET_CONTENT_TYPE); + getContentType = requestClass.getMethod(METHOD_GET_CONTENT_TYPE); securityRequest.setClientIP(String.valueOf(getRemoteAddr.invoke(requestObject))); securityRequest.setClientPort(String.valueOf(getRemotePort.invoke(requestObject))); securityRequest.setServerPort((int) getLocalPort.invoke(requestObject)); securityRequest.setProtocol((String) getScheme.invoke(requestObject)); securityRequest.setContentType((String) getContentType.invoke(requestObject)); - } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException | + } catch ( NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_2_16, e.getMessage()), e, HttpRequestHelper.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_2_16, e.getMessage()), e, HttpRequestHelper.class.getName()); @@ -253,12 +255,12 @@ public static void processPropertiesDelegate(PropertiesDelegate propertiesDelega } else if (StringUtils.equals(propertiesDelegate.getClass().getName(), ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_TRACING_AWARE_PROPERTIES_DELEGATE)){ try { - Class tracingAwarePropertiesDelegateKlass = getClass(TRACING_AWARE_PROPERTIES_DELEGATE); + Class tracingAwarePropertiesDelegateKlass = propertiesDelegate.getClass(); Field propertiesDelegateField = tracingAwarePropertiesDelegateKlass.getDeclaredField(FIELD_PROPERTIES_DELEGATE); propertiesDelegateField.setAccessible(true); Object propertiesDelegateObject = propertiesDelegateField.get(propertiesDelegate); processPropertiesDelegate((PropertiesDelegate) propertiesDelegateObject, securityRequest); - } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + } catch (NoSuchFieldException | IllegalAccessException e) { NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_2_16, e.getMessage()), e, HttpRequestHelper.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_2_16, e.getMessage()), e, HttpRequestHelper.class.getName()); } @@ -268,28 +270,6 @@ public static void processPropertiesDelegate(PropertiesDelegate propertiesDelega } } - private static Class getClass(String klassName) throws ClassNotFoundException { - switch (klassName) { - case GRIZZLY_REQUEST_PROPERTIES_DELEGATE: - if (grizzlyRequestPropertiesDelegateKlass == null) { - grizzlyRequestPropertiesDelegateKlass = Class.forName(ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_GRIZZLY_REQUEST_PROPERTIES_DELEGATE); - } - return grizzlyRequestPropertiesDelegateKlass; - case GRIZZLY_REQUEST: - if (grizzlyRequest == null) { - grizzlyRequest = Class.forName(ORG_GLASSFISH_GRIZZLY_HTTP_SERVER_REQUEST); - } - return grizzlyRequest; - case TRACING_AWARE_PROPERTIES_DELEGATE: - if (tracingAwarePropertiesDelegateKlass == null) { - tracingAwarePropertiesDelegateKlass = Class.forName(ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_TRACING_AWARE_PROPERTIES_DELEGATE); - } - return tracingAwarePropertiesDelegateKlass; - default: - throw new ClassNotFoundException(klassName); - } - } - public static void registerInputStreamHashIfNeeded(int inputStreamHash){ try { Set hashSet = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(REQUEST_INPUTSTREAM_HASH, Set.class); 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 29bc4f7e4..72c7e6ed2 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 @@ -232,22 +232,22 @@ private static String getNrSecCustomAttribName() { public static void processPropertiesDelegate(PropertiesDelegate propertiesDelegate, HttpRequest securityRequest) { if(StringUtils.equals(propertiesDelegate.getClass().getName(), ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_GRIZZLY_REQUEST_PROPERTIES_DELEGATE)){ try { - Class grizzlyRequestPropertiesDelegateKlass = getClass(GRIZZLY_REQUEST_PROPERTIES_DELEGATE); + Class grizzlyRequestPropertiesDelegateKlass = propertiesDelegate.getClass(); Field requestField = grizzlyRequestPropertiesDelegateKlass.getDeclaredField(FIELD_REQUEST); requestField.setAccessible(true); Object requestObject = requestField.get(propertiesDelegate); - Class requestClass = getClass(GRIZZLY_REQUEST); - Method getRemoteAddr = requestClass.getDeclaredMethod(METHOD_GET_REMOTE_ADDR); - Method getRemotePort = requestClass.getDeclaredMethod(METHOD_GET_REMOTE_PORT); - Method getLocalPort = requestClass.getDeclaredMethod(METHOD_GET_LOCAL_PORT); - Method getScheme = requestClass.getDeclaredMethod(METHOD_GET_SCHEME); - Method getContentType = requestClass.getDeclaredMethod(METHOD_GET_CONTENT_TYPE); + Class requestClass = requestObject.getClass(); + Method getRemoteAddr = requestClass.getMethod(METHOD_GET_REMOTE_ADDR); + Method getRemotePort = requestClass.getMethod(METHOD_GET_REMOTE_PORT); + Method getLocalPort = requestClass.getMethod(METHOD_GET_LOCAL_PORT); + Method getScheme = requestClass.getMethod(METHOD_GET_SCHEME); + Method getContentType = requestClass.getMethod(METHOD_GET_CONTENT_TYPE); securityRequest.setClientIP(String.valueOf(getRemoteAddr.invoke(requestObject))); securityRequest.setClientPort(String.valueOf(getRemotePort.invoke(requestObject))); securityRequest.setServerPort((int) getLocalPort.invoke(requestObject)); securityRequest.setProtocol((String) getScheme.invoke(requestObject)); securityRequest.setContentType((String) getContentType.invoke(requestObject)); - } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException | + } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_2, e.getMessage()), e, HttpRequestHelper.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_2, e.getMessage()), e, HttpRequestHelper.class.getName()); @@ -255,12 +255,12 @@ public static void processPropertiesDelegate(PropertiesDelegate propertiesDelega } else if (StringUtils.equals(propertiesDelegate.getClass().getName(), ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_TRACING_AWARE_PROPERTIES_DELEGATE)){ try { - Class tracingAwarePropertiesDelegateKlass = getClass(TRACING_AWARE_PROPERTIES_DELEGATE); + Class tracingAwarePropertiesDelegateKlass = propertiesDelegate.getClass(); Field propertiesDelegateField = tracingAwarePropertiesDelegateKlass.getDeclaredField(FIELD_PROPERTIES_DELEGATE); propertiesDelegateField.setAccessible(true); Object propertiesDelegateObject = propertiesDelegateField.get(propertiesDelegate); processPropertiesDelegate((PropertiesDelegate) propertiesDelegateObject, securityRequest); - } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + } catch (NoSuchFieldException | IllegalAccessException e) { NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_2, e.getMessage()), e, HttpRequestHelper.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_2, e.getMessage()), e, HttpRequestHelper.class.getName()); } @@ -270,28 +270,6 @@ public static void processPropertiesDelegate(PropertiesDelegate propertiesDelega } } - private static Class getClass(String klassName) throws ClassNotFoundException { - switch (klassName) { - case GRIZZLY_REQUEST_PROPERTIES_DELEGATE: - if (grizzlyRequestPropertiesDelegateKlass == null) { - grizzlyRequestPropertiesDelegateKlass = Class.forName(ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_GRIZZLY_REQUEST_PROPERTIES_DELEGATE); - } - return grizzlyRequestPropertiesDelegateKlass; - case GRIZZLY_REQUEST: - if (grizzlyRequest == null) { - grizzlyRequest = Class.forName(ORG_GLASSFISH_GRIZZLY_HTTP_SERVER_REQUEST); - } - return grizzlyRequest; - case TRACING_AWARE_PROPERTIES_DELEGATE: - if (tracingAwarePropertiesDelegateKlass == null) { - tracingAwarePropertiesDelegateKlass = Class.forName(ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_TRACING_AWARE_PROPERTIES_DELEGATE); - } - return tracingAwarePropertiesDelegateKlass; - default: - throw new ClassNotFoundException(klassName); - } - } - public static void registerInputStreamHashIfNeeded(int inputStreamHash){ try { Set hashSet = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(REQUEST_INPUTSTREAM_HASH, Set.class); 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 da34cf4f8..62bc4f3f6 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 @@ -230,22 +230,22 @@ private static String getNrSecCustomAttribName() { public static void processPropertiesDelegate(PropertiesDelegate propertiesDelegate, HttpRequest securityRequest) { if(StringUtils.equals(propertiesDelegate.getClass().getName(), ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_GRIZZLY_REQUEST_PROPERTIES_DELEGATE)){ try { - Class grizzlyRequestPropertiesDelegateKlass = getClass(GRIZZLY_REQUEST_PROPERTIES_DELEGATE); + Class grizzlyRequestPropertiesDelegateKlass = propertiesDelegate.getClass(); Field requestField = grizzlyRequestPropertiesDelegateKlass.getDeclaredField(FIELD_REQUEST); requestField.setAccessible(true); Object requestObject = requestField.get(propertiesDelegate); - Class requestClass = getClass(GRIZZLY_REQUEST); - Method getRemoteAddr = requestClass.getDeclaredMethod(METHOD_GET_REMOTE_ADDR); - Method getRemotePort = requestClass.getDeclaredMethod(METHOD_GET_REMOTE_PORT); - Method getLocalPort = requestClass.getDeclaredMethod(METHOD_GET_LOCAL_PORT); - Method getScheme = requestClass.getDeclaredMethod(METHOD_GET_SCHEME); - Method getContentType = requestClass.getDeclaredMethod(METHOD_GET_CONTENT_TYPE); + Class requestClass = requestObject.getClass(); + Method getRemoteAddr = requestClass.getMethod(METHOD_GET_REMOTE_ADDR); + Method getRemotePort = requestClass.getMethod(METHOD_GET_REMOTE_PORT); + Method getLocalPort = requestClass.getMethod(METHOD_GET_LOCAL_PORT); + Method getScheme = requestClass.getMethod(METHOD_GET_SCHEME); + Method getContentType = requestClass.getMethod(METHOD_GET_CONTENT_TYPE); securityRequest.setClientIP(String.valueOf(getRemoteAddr.invoke(requestObject))); securityRequest.setClientPort(String.valueOf(getRemotePort.invoke(requestObject))); securityRequest.setServerPort((int) getLocalPort.invoke(requestObject)); securityRequest.setProtocol((String) getScheme.invoke(requestObject)); securityRequest.setContentType((String) getContentType.invoke(requestObject)); - } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException | + } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_3, e.getMessage()), e, HttpRequestHelper.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_3, e.getMessage()), e, HttpRequestHelper.class.getName()); @@ -253,12 +253,12 @@ public static void processPropertiesDelegate(PropertiesDelegate propertiesDelega } else if (StringUtils.equals(propertiesDelegate.getClass().getName(), ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_TRACING_AWARE_PROPERTIES_DELEGATE)){ try { - Class tracingAwarePropertiesDelegateKlass = getClass(TRACING_AWARE_PROPERTIES_DELEGATE); + Class tracingAwarePropertiesDelegateKlass = propertiesDelegate.getClass(); Field propertiesDelegateField = tracingAwarePropertiesDelegateKlass.getDeclaredField(FIELD_PROPERTIES_DELEGATE); propertiesDelegateField.setAccessible(true); Object propertiesDelegateObject = propertiesDelegateField.get(propertiesDelegate); processPropertiesDelegate((PropertiesDelegate) propertiesDelegateObject, securityRequest); - } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + } catch (NoSuchFieldException | IllegalAccessException e) { NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_3, e.getMessage()), e, HttpRequestHelper.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, JERSEY_3, e.getMessage()), e, HttpRequestHelper.class.getName()); } @@ -268,28 +268,6 @@ public static void processPropertiesDelegate(PropertiesDelegate propertiesDelega } } - private static Class getClass(String klassName) throws ClassNotFoundException { - switch (klassName) { - case GRIZZLY_REQUEST_PROPERTIES_DELEGATE: - if (grizzlyRequestPropertiesDelegateKlass == null) { - grizzlyRequestPropertiesDelegateKlass = Class.forName(ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_GRIZZLY_REQUEST_PROPERTIES_DELEGATE); - } - return grizzlyRequestPropertiesDelegateKlass; - case GRIZZLY_REQUEST: - if (grizzlyRequest == null) { - grizzlyRequest = Class.forName(ORG_GLASSFISH_GRIZZLY_HTTP_SERVER_REQUEST); - } - return grizzlyRequest; - case TRACING_AWARE_PROPERTIES_DELEGATE: - if (tracingAwarePropertiesDelegateKlass == null) { - tracingAwarePropertiesDelegateKlass = Class.forName(ORG_GLASSFISH_JERSEY_GRIZZLY_2_HTTPSERVER_TRACING_AWARE_PROPERTIES_DELEGATE); - } - return tracingAwarePropertiesDelegateKlass; - default: - throw new ClassNotFoundException(klassName); - } - } - public static void registerInputStreamHashIfNeeded(int inputStreamHash){ try { Set hashSet = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(REQUEST_INPUTSTREAM_HASH, Set.class); From 52b548dcbc5111486dbef5ad1a4e62c9e469f25e Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 4 Jul 2024 11:50:51 +0530 Subject: [PATCH 009/122] Support for event generation of type SQLR_DB_OPERATIONS via HTTP client --- .../solr-4.0.0/build.gradle | 34 +++++ .../impl/HttpSolrServer_Instrumentation.java | 112 ++++++++++++++++ .../solr-5.0.0/build.gradle | 32 +++++ .../impl/HttpSolrClient_Instrumentation.java | 113 ++++++++++++++++ .../solr-7.0.0/build.gradle | 29 ++++ .../impl/HttpSolrClient_Instrumentation.java | 125 ++++++++++++++++++ .../instrumentator/dispatcher/Dispatcher.java | 18 +++ .../schema/VulnerabilityCaseType.java | 4 +- .../schema/operation/SolrDbOperation.java | 85 ++++++++++++ settings.gradle | 3 + 10 files changed, 554 insertions(+), 1 deletion(-) create mode 100644 instrumentation-security/solr-4.0.0/build.gradle create mode 100644 instrumentation-security/solr-4.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrServer_Instrumentation.java create mode 100644 instrumentation-security/solr-5.0.0/build.gradle create mode 100644 instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java create mode 100644 instrumentation-security/solr-7.0.0/build.gradle create mode 100644 instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SolrDbOperation.java diff --git a/instrumentation-security/solr-4.0.0/build.gradle b/instrumentation-security/solr-4.0.0/build.gradle new file mode 100644 index 000000000..7db53c675 --- /dev/null +++ b/instrumentation-security/solr-4.0.0/build.gradle @@ -0,0 +1,34 @@ +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.lucene:lucene-core:4.0.0") + + implementation("org.apache.solr:solr-core:4.0.0") { + transitive = false + } + implementation("org.apache.solr:solr-solrj:4.0.0") { + transitive = false + } + implementation("org.apache.httpcomponents:httpclient:4.1.3") { + transitive = false + } +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.solr-4.0.0' } +} + +verifyInstrumentation { + passesOnly 'org.apache.solr:solr-core:[4.0.0,5.0.0)' + + exclude 'org.apache.solr:solr-core:[0,1.4.0)' + + excludeRegex 'org.apache.solr:solr-core:.*(ALPHA|BETA)+$' +} + +site { + title 'Solr' + type 'Datastore' +} \ No newline at end of file diff --git a/instrumentation-security/solr-4.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrServer_Instrumentation.java b/instrumentation-security/solr-4.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrServer_Instrumentation.java new file mode 100644 index 000000000..f7afcb950 --- /dev/null +++ b/instrumentation-security/solr-4.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrServer_Instrumentation.java @@ -0,0 +1,112 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.apache.solr.client.solrj.impl; + +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.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.SolrDbOperation; +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 org.apache.http.client.HttpClient; +import org.apache.solr.client.solrj.ResponseParser; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.request.UpdateRequest; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.HttpSolrServer") +public abstract class HttpSolrServer_Instrumentation { + + public abstract String getBaseURL(); + + public HttpSolrServer_Instrumentation(String baseURL, HttpClient client, ResponseParser parser) { + //TODO report external URL + } + + public NamedList request(final SolrRequest request, ResponseParser processor) { + boolean isLockAcquired = GenericHelper.acquireLockIfPossible("HTTP_SOLR_REQUEST-", request.hashCode()); + AbstractOperation operation = null; + if(isLockAcquired) { + operation = preprocessSolrRequest(request, "REQUEST"); + } + NamedList result; + try { + result = Weaver.callOriginal(); + } finally { + if(isLockAcquired) { + GenericHelper.releaseLock("HTTP_SOLR_REQUEST-", request.hashCode()); + } + } + registerExitOperation(isLockAcquired, operation); + return result; + } + + private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || GenericHelper.skipExistsEvent() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e){ + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + } + + private AbstractOperation preprocessSolrRequest(SolrRequest request, String methodName) { + try { + String collection = new URL(getBaseURL()).getPath(); + collection = collection.startsWith("/") ? collection.substring(1) : collection; + String method = request.getMethod().toString(); + String path = request.getPath(); + SolrParams solrParams = request.getParams(); + Map params = Collections.emptyMap(); + if(solrParams != null){ + params = SolrParams.toMap(solrParams.toNamedList()); + } + List documents = Collections.emptyList(); + if(request instanceof UpdateRequest) { + documents = ((UpdateRequest) request).getDocuments(); + } + SolrDbOperation solrDbOperation = new SolrDbOperation(this.getClass().getName(), methodName); + solrDbOperation.setCollection(collection); + solrDbOperation.setParams(params); + solrDbOperation.setDocuments(documents); + solrDbOperation.setConnectionURL(getBaseURL()); + solrDbOperation.setMethod(method); + solrDbOperation.setPath(path); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Solr request %s, %s, %s, %s, %s", collection, method, path, params, documents), this.getClass().getName()); + NewRelicSecurity.getAgent().registerOperation(solrDbOperation); + return solrDbOperation; + } catch (MalformedURLException e){ + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + return null; + } + +} diff --git a/instrumentation-security/solr-5.0.0/build.gradle b/instrumentation-security/solr-5.0.0/build.gradle new file mode 100644 index 000000000..236ad5a39 --- /dev/null +++ b/instrumentation-security/solr-5.0.0/build.gradle @@ -0,0 +1,32 @@ +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.lucene:lucene-core:4.0.0") + + implementation("org.apache.solr:solr-core:5.0.0") { + transitive = false + } + implementation("org.apache.solr:solr-solrj:5.0.0") { + transitive = false + } + implementation("org.apache.httpcomponents:httpclient:4.3.1") { + transitive = false + } +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.solr-5.0.0' } +} + +verifyInstrumentation { + passesOnly 'org.apache.solr:solr-core:[5.0.0,7.0.0)' + + excludeRegex 'org.apache.solr:solr-core:.*(ALPHA|BETA)+$' +} + +site { + title 'Solr' + type 'Datastore' +} \ No newline at end of file diff --git a/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java b/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java new file mode 100644 index 000000000..36545b366 --- /dev/null +++ b/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java @@ -0,0 +1,113 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.apache.solr.client.solrj.impl; +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.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.SolrDbOperation; +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 org.apache.http.client.HttpClient; +import org.apache.solr.client.solrj.ResponseParser; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.request.UpdateRequest; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.HttpSolrClient") +public abstract class HttpSolrClient_Instrumentation { + + public abstract String getBaseURL(); + + public HttpSolrClient_Instrumentation(String baseURL, HttpClient client, ResponseParser parser) { + //TODO report external URL + } + + public NamedList request(final SolrRequest request, final ResponseParser processor) { + boolean isLockAcquired = GenericHelper.acquireLockIfPossible("HTTP_SOLR_REQUEST-", request.hashCode()); + AbstractOperation operation = null; + if(isLockAcquired) { + operation = preprocessSolrRequest(request, "REQUEST"); + } + NamedList result; + try { + result = Weaver.callOriginal(); + } finally { + if(isLockAcquired) { + GenericHelper.releaseLock("HTTP_SOLR_REQUEST-", request.hashCode()); + } + } + registerExitOperation(isLockAcquired, operation); + return result; + } + + private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || GenericHelper.skipExistsEvent() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e){ + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + } + + private AbstractOperation preprocessSolrRequest(SolrRequest request, String methodName) { + try { + String collection = new URL(getBaseURL()).getPath(); + collection = collection.startsWith("/") ? collection.substring(1) : collection; + String method = request.getMethod().toString(); + String path = request.getPath(); + SolrParams solrParams = request.getParams(); + Map params = Collections.emptyMap(); + if(solrParams != null){ + params = SolrParams.toMap(solrParams.toNamedList()); + } + List documents = Collections.emptyList(); + if(request instanceof UpdateRequest) { + documents = ((UpdateRequest) request).getDocuments(); + } + SolrDbOperation solrDbOperation = new SolrDbOperation(this.getClass().getName(), methodName); + solrDbOperation.setCollection(collection); + solrDbOperation.setParams(params); + solrDbOperation.setDocuments(documents); + solrDbOperation.setConnectionURL(getBaseURL()); + solrDbOperation.setMethod(method); + solrDbOperation.setPath(path); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Solr request %s, %s, %s, %s, %s", collection, method, path, params, documents), this.getClass().getName()); + NewRelicSecurity.getAgent().registerOperation(solrDbOperation); + return solrDbOperation; + } catch (MalformedURLException e){ + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + return null; + } + +} diff --git a/instrumentation-security/solr-7.0.0/build.gradle b/instrumentation-security/solr-7.0.0/build.gradle new file mode 100644 index 000000000..e416374a6 --- /dev/null +++ b/instrumentation-security/solr-7.0.0/build.gradle @@ -0,0 +1,29 @@ +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.lucene:lucene-core:4.0.0") + + implementation("org.apache.solr:solr-core:7.0.0") { + transitive = false + } + implementation("org.apache.solr:solr-solrj:7.0.0") { + transitive = false + } +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.solr-7.0.0' } +} + +verifyInstrumentation { + passesOnly 'org.apache.solr:solr-core:[7.0.0,)' + + excludeRegex 'org.apache.solr:solr-core:.*(ALPHA|BETA)+$' +} + +site { + title 'Solr' + type 'Datastore' +} \ No newline at end of file diff --git a/instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java b/instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java new file mode 100644 index 000000000..bb8bfd0db --- /dev/null +++ b/instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java @@ -0,0 +1,125 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.apache.solr.client.solrj.impl; +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.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.SolrDbOperation; +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 org.apache.solr.client.solrj.ResponseParser; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.request.UpdateRequest; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.HttpSolrClient") +public abstract class HttpSolrClient_Instrumentation { + + + public abstract String getBaseURL(); + + protected HttpSolrClient_Instrumentation(Builder builder) { + //TODO report external URL + } + + public NamedList request(@SuppressWarnings({"rawtypes"})final SolrRequest request, final ResponseParser processor, String collection) + throws SolrServerException, IOException { + boolean isLockAcquired = GenericHelper.acquireLockIfPossible("HTTP_SOLR_REQUEST-", request.hashCode()); + AbstractOperation operation = null; + if(isLockAcquired) { + operation = preprocessSolrRequest(request, "REQUEST"); + } + NamedList result; + try { + result = Weaver.callOriginal(); + } finally { + if(isLockAcquired) { + GenericHelper.releaseLock("HTTP_SOLR_REQUEST-", request.hashCode()); + } + } + registerExitOperation(isLockAcquired, operation); + return result; + } + + private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || GenericHelper.skipExistsEvent() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e){ + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + } + + private AbstractOperation preprocessSolrRequest(@SuppressWarnings({"rawtypes"})SolrRequest request, String methodName) { + try { + String collection = new URL(getBaseURL()).getPath(); + collection = collection.startsWith("/") ? collection.substring(1) : collection; + String method = request.getMethod().toString(); + String path = request.getPath(); + SolrParams solrParams = request.getParams(); + Map params = Collections.emptyMap(); + if(solrParams != null){ + params = SolrParams.toMap(solrParams.toNamedList()); + } + List documents = Collections.emptyList(); + if(request instanceof UpdateRequest) { + documents = ((UpdateRequest) request).getDocuments(); + } + SolrDbOperation solrDbOperation = new SolrDbOperation(this.getClass().getName(), methodName); + solrDbOperation.setCollection(collection); + solrDbOperation.setParams(params); + solrDbOperation.setDocuments(documents); + solrDbOperation.setConnectionURL(getBaseURL()); + solrDbOperation.setMethod(method); + solrDbOperation.setPath(path); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Solr request %s, %s, %s, %s, %s", collection, method, path, params, documents), this.getClass().getName()); + NewRelicSecurity.getAgent().registerOperation(solrDbOperation); + return solrDbOperation; + } catch (MalformedURLException e){ + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + return null; + } + + @Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.HttpSolrClient$Builder") + public static class Builder extends SolrClientBuilder { + protected String baseSolrUrl; + + @Override + public Builder getThis() { + return this; + } + } + +} 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 9aa06df9e..e01b4727a 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 @@ -221,6 +221,10 @@ public Object call() throws Exception { eventBean = prepareMemcachedEvent(eventBean, memcachedOperationalBean); } break; + case SOLR_DB_REQUEST: + SolrDbOperation solrDbOperation = (SolrDbOperation) operation; + eventBean = prepareSolrDbRequestEvent(eventBean, solrDbOperation); + break; default: } @@ -252,6 +256,20 @@ public Object call() throws Exception { return null; } + private JavaAgentEventBean prepareSolrDbRequestEvent(JavaAgentEventBean eventBean, SolrDbOperation solrDbOperation) { + JSONArray params = new JSONArray(); + JSONObject request = new JSONObject(); + request.put("collection", solrDbOperation.getCollection()); + request.put("method", solrDbOperation.getMethod()); + request.put("connectionURL", solrDbOperation.getConnectionURL()); + request.put("path", solrDbOperation.getPath()); + request.put("params", solrDbOperation.getParams()); + request.put("documents", solrDbOperation.getDocuments()); + params.add(request); + eventBean.setParameters(params); + return eventBean; + } + private JavaAgentEventBean prepareCachingDataStoreEvent(JavaAgentEventBean eventBean, RedisOperation redisOperation) { JSONArray params = new JSONArray(); for (Object data : redisOperation.getArguments()) { diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/VulnerabilityCaseType.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/VulnerabilityCaseType.java index 1eb329436..a3d8a31d2 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/VulnerabilityCaseType.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/VulnerabilityCaseType.java @@ -69,7 +69,9 @@ public enum VulnerabilityCaseType { /** JavaScript Injection */ XQUERY_INJECTION("XQUERY_INJECTION"), - CACHING_DATA_STORE("CACHING_DATA_STORE"); + CACHING_DATA_STORE("CACHING_DATA_STORE"), + + SOLR_DB_REQUEST("SOLR_DB_REQUEST"); /** case type. */ diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SolrDbOperation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SolrDbOperation.java new file mode 100644 index 000000000..ec8ae0353 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SolrDbOperation.java @@ -0,0 +1,85 @@ +package com.newrelic.api.agent.security.schema.operation; + +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 java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public class SolrDbOperation extends AbstractOperation { + + private String collection; + + private String method; + + private String connectionURL; + + private String path; + + private Map params; + + private List documents; + + public SolrDbOperation(String className, String methodName) { + super(className, methodName); + this.setCaseType(VulnerabilityCaseType.SOLR_DB_REQUEST); + } + + public String getCollection() { + return collection; + } + + public void setCollection(String collection) { + this.collection = collection; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public String getConnectionURL() { + return connectionURL; + } + + public void setConnectionURL(String connectionURL) { + this.connectionURL = connectionURL; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Map getParams() { + return params; + } + + public void setParams(Map params) { + this.params = params; + } + + public List getDocuments() { + return documents; + } + + public void setDocuments(List documents) { + this.documents = documents; + } + + @Override + public boolean isEmpty() { + return method == null || method.trim().isEmpty() || connectionURL == null || connectionURL.trim().isEmpty() + || path == null || path.trim().isEmpty(); + } +} + diff --git a/settings.gradle b/settings.gradle index ca13695b0..30b633a6d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -209,3 +209,6 @@ include 'instrumentation:weblogic-12.2' include 'instrumentation:jedis-4.0.0' include 'instrumentation:jedis-3.0.0' include 'instrumentation:jedis-2.7.1_2.7.2' +include 'instrumentation:solr-4.0.0' +include 'instrumentation:solr-5.0.0' +include 'instrumentation:solr-7.0.0' From 22471977a791e42eccc3afaa26b53dfdd06fb476 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 4 Jul 2024 16:27:55 +0530 Subject: [PATCH 010/122] Unit tests for spring route detection --- .../spring/webmvc/APIEndpointTest.java | 21 +- .../spring/webmvc/DummyRequest.java | 328 +++++++++++++++ .../spring/webmvc/APIEndpointTest.java | 22 +- .../spring/webmvc/DummyRequest.java | 328 +++++++++++++++ .../spring/webmvc/APIEndpointTest.java | 22 +- .../spring/webmvc/DummyRequest.java | 380 ++++++++++++++++++ 6 files changed, 1098 insertions(+), 3 deletions(-) create mode 100644 instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java create mode 100644 instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java create mode 100644 instrumentation-security/spring-webmvc-6.0.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java 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 index 8c10e6923..772d0ed51 100644 --- 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 @@ -4,12 +4,15 @@ 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.api.agent.security.schema.Framework; +import com.newrelic.api.agent.security.schema.SecurityMetaData; 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 javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Set; @@ -34,7 +37,7 @@ public static void addMappings() { } @Test - public void testAPIEndpointDetection() { + public void testAPIEndpointDetection() throws Exception { methodMapping.addMapping(new TestMappings()); Set mappings = URLMappingsHelper.getApplicationURLMappings(); @@ -42,9 +45,22 @@ public void testAPIEndpointDetection() { for (ApplicationURLMapping mapping: mappings) { Assert.assertNotNull(mapping); + // Assertions for URL Mappings assertMapping(mapping); + + // Assertions for Route Detection + assertRouteDetection(mapping); } + } + + private void assertRouteDetection(ApplicationURLMapping mapping) throws Exception { + methodMapping.handleRequest(new DummyRequest(mapping.getPath(), mapping.getMethod())); + SecurityMetaData metaData = SecurityInstrumentationTestRunner.getIntrospector().getSecurityMetaData(); + Assert.assertFalse(metaData.getRequest().getRoute().isEmpty()); + Assert.assertEquals(mapping.getPath(), metaData.getRequest().getRoute()); + + Assert.assertEquals(Framework.SPRING_WEB_MVC.name(), metaData.getMetaData().getFramework()); } private void assertMapping(ApplicationURLMapping actualMapping) { @@ -60,4 +76,7 @@ class TestHandlerMethodMapping extends RequestMappingHandlerMapping { public void addMapping(Object handler) { super.detectHandlerMethods(handler); } + public void handleRequest(HttpServletRequest request) throws Exception { + super.getHandlerInternal(request); + } } diff --git a/instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java b/instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java new file mode 100644 index 000000000..7c1eb6248 --- /dev/null +++ b/instrumentation-security/spring-webmvc-3.1.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java @@ -0,0 +1,328 @@ +package com.nr.agent.security.instrumentation.spring.webmvc; + +import com.newrelic.api.agent.security.schema.StringUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Map; +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; + +public class DummyRequest implements HttpServletRequest { + protected String queryString = StringUtils.EMPTY; + protected String pathInfo; + protected String servletPath = StringUtils.SEPARATOR; + private String method; + private static Enumeration dummyEnum = new Enumeration() { + public boolean hasMoreElements() { + return false; + } + + public String nextElement() { + return null; + } + }; + + public DummyRequest(String pathInfo, String method) { + this.pathInfo = pathInfo; + this.method = method; + } + + public String getContextPath() { + return null; + } + + public ServletRequest getRequest() { + return this; + } + + public String getQueryString() { + return this.queryString; + } + + public String getPathInfo() { + return this.pathInfo; + } + + public String getServletPath() { + return this.servletPath; + } + + public String getMethod() { + return this.method; + } + + public Object getAttribute(String name) { + return pathInfo; + } + + public Enumeration getAttributeNames() { + return null; + } + + public String getCharacterEncoding() { + return null; + } + + public int getContentLength() { + return -1; + } + + public long getContentLengthLong() { + return -1L; + } + + public String getContentType() { + return null; + } + + public ServletInputStream getInputStream() throws IOException { + return null; + } + + public Locale getLocale() { + return null; + } + + public Enumeration getLocales() { + return null; + } + + public String getProtocol() { + return null; + } + + public BufferedReader getReader() throws IOException { + return null; + } + + public String getRealPath(String path) { + return null; + } + + public String getRemoteAddr() { + return null; + } + + public String getRemoteHost() { + return null; + } + + public String getScheme() { + return null; + } + + public String getServerName() { + return null; + } + + public int getServerPort() { + return -1; + } + + public boolean isSecure() { + return false; + } + + public void removeAttribute(String name) { + } + + public void setAttribute(String name, Object value) { + } + + public void setCharacterEncoding(String enc) throws UnsupportedEncodingException { + } + + public String getParameter(String name) { + return null; + } + + public Map getParameterMap() { + return null; + } + + public Enumeration getParameterNames() { + return dummyEnum; + } + + public String[] getParameterValues(String name) { + return null; + } + + public RequestDispatcher getRequestDispatcher(String path) { + return null; + } + + public String getAuthType() { + return null; + } + + public Cookie[] getCookies() { + return null; + } + + public long getDateHeader(String name) { + return -1L; + } + + public String getHeader(String name) { + return null; + } + + public Enumeration getHeaders(String name) { + return null; + } + + public Enumeration getHeaderNames() { + return null; + } + + public int getIntHeader(String name) { + return -1; + } + + public String getPathTranslated() { + return null; + } + + public String getRemoteUser() { + return null; + } + + public String getRequestedSessionId() { + return null; + } + + public String getRequestURI() { + return null; + } + + public StringBuffer getRequestURL() { + return null; + } + + public HttpSession getSession() { + return null; + } + + public HttpSession getSession(boolean create) { + return null; + } + + public String changeSessionId() { + return null; + } + + public boolean isRequestedSessionIdFromCookie() { + return false; + } + + public boolean isRequestedSessionIdFromURL() { + return false; + } + + public boolean isRequestedSessionIdFromUrl() { + return false; + } + + public boolean isRequestedSessionIdValid() { + return false; + } + + public void setRequestedSessionCookiePath(String cookiePath) { + } + + public boolean isUserInRole(String role) { + return false; + } + + public Principal getUserPrincipal() { + return null; + } + + public String getLocalAddr() { + return null; + } + + public String getLocalName() { + return null; + } + + public int getLocalPort() { + return -1; + } + + public int getRemotePort() { + return -1; + } + + public DispatcherType getDispatcherType() { + return null; + } + + public AsyncContext startAsync() throws IllegalStateException { + return null; + } + + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { + return null; + } + + public boolean isAsyncStarted() { + return false; + } + + public boolean isAsyncSupported() { + return false; + } + + public AsyncContext getAsyncContext() { + return null; + } + + public Collection getParts() { + return null; + } + + public Part getPart(String name) { + return null; + } + + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + return false; + } + + public void login(String username, String password) throws ServletException { + } + + public void logout() throws ServletException { + + } + + public T upgrade(Class handlerClass) { + return null; + } + + public ServletContext getServletContext() { + return null; + } + +} + 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 index d1b94dc24..31b25d089 100644 --- 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 @@ -4,12 +4,15 @@ 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.api.agent.security.schema.Framework; +import com.newrelic.api.agent.security.schema.SecurityMetaData; 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 javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Set; @@ -34,7 +37,7 @@ public static void addMappings() { } @Test - public void testAPIEndpointDetection() { + public void testAPIEndpointDetection() throws Exception { methodMapping.addMapping(new TestMappings()); Set mappings = URLMappingsHelper.getApplicationURLMappings(); @@ -42,9 +45,22 @@ public void testAPIEndpointDetection() { for (ApplicationURLMapping mapping: mappings) { Assert.assertNotNull(mapping); + // Assertions for URL Mappings assertMapping(mapping); + + // Assertions for Route Detection + assertRouteDetection(mapping); } + } + + private void assertRouteDetection(ApplicationURLMapping mapping) throws Exception { + methodMapping.handleRequest(new DummyRequest(mapping.getPath(), mapping.getMethod())); + SecurityMetaData metaData = SecurityInstrumentationTestRunner.getIntrospector().getSecurityMetaData(); + Assert.assertFalse(metaData.getRequest().getRoute().isEmpty()); + Assert.assertEquals(mapping.getPath(), metaData.getRequest().getRoute()); + + Assert.assertEquals(Framework.SPRING_WEB_MVC.name(), metaData.getMetaData().getFramework()); } private void assertMapping(ApplicationURLMapping actualMapping) { @@ -60,4 +76,8 @@ class TestHandlerMethodMapping extends RequestMappingHandlerMapping { public void addMapping(Object handler) { super.detectHandlerMethods(handler); } + + public void handleRequest(HttpServletRequest request) throws Exception { + super.getHandlerInternal(request); + } } \ 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/DummyRequest.java b/instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java new file mode 100644 index 000000000..69c965f96 --- /dev/null +++ b/instrumentation-security/spring-webmvc-5.3.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java @@ -0,0 +1,328 @@ +package com.nr.agent.security.instrumentation.spring.webmvc; + +import com.newrelic.api.agent.security.schema.StringUtils; + +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Map; + +public class DummyRequest implements HttpServletRequest { + protected String queryString = StringUtils.EMPTY; + protected String pathInfo; + protected String servletPath = StringUtils.SEPARATOR; + private String method; + private static Enumeration dummyEnum = new Enumeration() { + public boolean hasMoreElements() { + return false; + } + + public String nextElement() { + return null; + } + }; + + public DummyRequest(String pathInfo, String method) { + this.pathInfo = pathInfo; + this.method = method; + } + + public String getContextPath() { + return null; + } + + public ServletRequest getRequest() { + return this; + } + + public String getQueryString() { + return this.queryString; + } + + public String getPathInfo() { + return this.pathInfo; + } + + public String getServletPath() { + return this.servletPath; + } + + public String getMethod() { + return this.method; + } + + public Object getAttribute(String name) { + return pathInfo; + } + + public Enumeration getAttributeNames() { + return null; + } + + public String getCharacterEncoding() { + return null; + } + + public int getContentLength() { + return -1; + } + + public long getContentLengthLong() { + return -1L; + } + + public String getContentType() { + return null; + } + + public ServletInputStream getInputStream() throws IOException { + return null; + } + + public Locale getLocale() { + return null; + } + + public Enumeration getLocales() { + return null; + } + + public String getProtocol() { + return null; + } + + public BufferedReader getReader() throws IOException { + return null; + } + + public String getRealPath(String path) { + return null; + } + + public String getRemoteAddr() { + return null; + } + + public String getRemoteHost() { + return null; + } + + public String getScheme() { + return null; + } + + public String getServerName() { + return null; + } + + public int getServerPort() { + return -1; + } + + public boolean isSecure() { + return false; + } + + public void removeAttribute(String name) { + } + + public void setAttribute(String name, Object value) { + } + + public void setCharacterEncoding(String enc) throws UnsupportedEncodingException { + } + + public String getParameter(String name) { + return null; + } + + public Map getParameterMap() { + return null; + } + + public Enumeration getParameterNames() { + return dummyEnum; + } + + public String[] getParameterValues(String name) { + return null; + } + + public RequestDispatcher getRequestDispatcher(String path) { + return null; + } + + public String getAuthType() { + return null; + } + + public Cookie[] getCookies() { + return null; + } + + public long getDateHeader(String name) { + return -1L; + } + + public String getHeader(String name) { + return null; + } + + public Enumeration getHeaders(String name) { + return null; + } + + public Enumeration getHeaderNames() { + return null; + } + + public int getIntHeader(String name) { + return -1; + } + + public String getPathTranslated() { + return null; + } + + public String getRemoteUser() { + return null; + } + + public String getRequestedSessionId() { + return null; + } + + public String getRequestURI() { + return null; + } + + public StringBuffer getRequestURL() { + return null; + } + + public HttpSession getSession() { + return null; + } + + public HttpSession getSession(boolean create) { + return null; + } + + public String changeSessionId() { + return null; + } + + public boolean isRequestedSessionIdFromCookie() { + return false; + } + + public boolean isRequestedSessionIdFromURL() { + return false; + } + + public boolean isRequestedSessionIdFromUrl() { + return false; + } + + public boolean isRequestedSessionIdValid() { + return false; + } + + public void setRequestedSessionCookiePath(String cookiePath) { + } + + public boolean isUserInRole(String role) { + return false; + } + + public Principal getUserPrincipal() { + return null; + } + + public String getLocalAddr() { + return null; + } + + public String getLocalName() { + return null; + } + + public int getLocalPort() { + return -1; + } + + public int getRemotePort() { + return -1; + } + + public DispatcherType getDispatcherType() { + return null; + } + + public AsyncContext startAsync() throws IllegalStateException { + return null; + } + + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { + return null; + } + + public boolean isAsyncStarted() { + return false; + } + + public boolean isAsyncSupported() { + return false; + } + + public AsyncContext getAsyncContext() { + return null; + } + + public Collection getParts() { + return null; + } + + public Part getPart(String name) { + return null; + } + + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + return false; + } + + public void login(String username, String password) throws ServletException { + } + + public void logout() throws ServletException { + + } + + public T upgrade(Class handlerClass) { + return null; + } + + public ServletContext getServletContext() { + return null; + } + +} + diff --git a/instrumentation-security/spring-webmvc-6.0.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java b/instrumentation-security/spring-webmvc-6.0.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java index d1b94dc24..168b08ae3 100644 --- a/instrumentation-security/spring-webmvc-6.0.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java +++ b/instrumentation-security/spring-webmvc-6.0.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/APIEndpointTest.java @@ -4,6 +4,9 @@ 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.api.agent.security.schema.Framework; +import com.newrelic.api.agent.security.schema.SecurityMetaData; +import jakarta.servlet.http.HttpServletRequest; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -34,7 +37,7 @@ public static void addMappings() { } @Test - public void testAPIEndpointDetection() { + public void testAPIEndpointDetection() throws Exception { methodMapping.addMapping(new TestMappings()); Set mappings = URLMappingsHelper.getApplicationURLMappings(); @@ -42,9 +45,22 @@ public void testAPIEndpointDetection() { for (ApplicationURLMapping mapping: mappings) { Assert.assertNotNull(mapping); + // Assertions for URL Mappings assertMapping(mapping); + + // Assertions for Route Detection + assertRouteDetection(mapping); } + } + + private void assertRouteDetection(ApplicationURLMapping mapping) throws Exception { + methodMapping.handleRequest(new DummyRequest(mapping.getPath(), mapping.getMethod())); + SecurityMetaData metaData = SecurityInstrumentationTestRunner.getIntrospector().getSecurityMetaData(); + Assert.assertFalse(metaData.getRequest().getRoute().isEmpty()); + Assert.assertEquals(mapping.getPath(), metaData.getRequest().getRoute()); + + Assert.assertEquals(Framework.SPRING_WEB_MVC.name(), metaData.getMetaData().getFramework()); } private void assertMapping(ApplicationURLMapping actualMapping) { @@ -60,4 +76,8 @@ class TestHandlerMethodMapping extends RequestMappingHandlerMapping { public void addMapping(Object handler) { super.detectHandlerMethods(handler); } + + public void handleRequest(HttpServletRequest request) throws Exception { + super.getHandlerInternal(request); + } } \ No newline at end of file diff --git a/instrumentation-security/spring-webmvc-6.0.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java b/instrumentation-security/spring-webmvc-6.0.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java new file mode 100644 index 000000000..a68695bbb --- /dev/null +++ b/instrumentation-security/spring-webmvc-6.0.0/src/test/java/com/nr/agent/security/instrumentation/spring/webmvc/DummyRequest.java @@ -0,0 +1,380 @@ +package com.nr.agent.security.instrumentation.spring.webmvc; + +import com.newrelic.api.agent.security.schema.StringUtils; + +import jakarta.servlet.AsyncContext; +import jakarta.servlet.DispatcherType; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import jakarta.servlet.http.HttpUpgradeHandler; +import jakarta.servlet.http.Part; +import org.springframework.http.server.PathContainer; +import org.springframework.http.server.RequestPath; +import org.springframework.web.util.ServletRequestPathUtils; +import org.springframework.web.util.UrlPathHelper; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +public class DummyRequest implements HttpServletRequest { + protected String queryString = StringUtils.EMPTY; + protected String pathInfo; + protected String servletPath = StringUtils.SEPARATOR; + private String method; + private static Enumeration dummyEnum = new Enumeration() { + public boolean hasMoreElements() { + return false; + } + + public String nextElement() { + return null; + } + }; + + public DummyRequest(String pathInfo, String method) { + this.pathInfo = pathInfo; + this.method = method; + } + + public String getContextPath() { + return null; + } + + public String getQueryString() { + return this.queryString; + } + + public String getPathInfo() { + return this.pathInfo; + } + + public String getServletPath() { + return this.servletPath; + } + + public String getMethod() { + return this.method; + } + + public Object getAttribute(String name) { + if (name.equals(ServletRequestPathUtils.class.getName() + ".PATH")) { + return new RequestPath() { + @Override + public PathContainer contextPath() { + return new PathContainer() { + @Override + public String value() { + return pathInfo; + } + + @Override + public List elements() { + return Collections.emptyList(); + } + }; + } + + @Override + public PathContainer pathWithinApplication() { + return new PathContainer() { + @Override + public String value() { + return pathInfo; + } + + @Override + public List elements() { + return Collections.emptyList(); + } + }; + } + + @Override + public RequestPath modifyContextPath(String contextPath) { + return this; + } + + @Override + public String value() { + return ""; + } + + @Override + public List elements() { + return Collections.emptyList(); + } + }; + } else if (name.equals(UrlPathHelper.class.getName() + ".PATH") || name.equals("jakarta.servlet.include.request_uri")){ + return pathInfo; + } else { + return null; + } + } + + public Enumeration getAttributeNames() { + return null; + } + + public String getCharacterEncoding() { + return null; + } + + public int getContentLength() { + return -1; + } + + public long getContentLengthLong() { + return -1L; + } + + public String getContentType() { + return null; + } + + public ServletInputStream getInputStream() throws IOException { + return null; + } + + public Locale getLocale() { + return null; + } + + public Enumeration getLocales() { + return null; + } + + public String getProtocol() { + return null; + } + + public BufferedReader getReader() throws IOException { + return null; + } + + public String getRealPath(String path) { + return null; + } + + public String getRemoteAddr() { + return null; + } + + public String getRemoteHost() { + return null; + } + + public String getScheme() { + return null; + } + + public String getServerName() { + return null; + } + + public int getServerPort() { + return -1; + } + + public boolean isSecure() { + return false; + } + + public void removeAttribute(String name) { + } + + public void setAttribute(String name, Object value) { + } + + public void setCharacterEncoding(String enc) throws UnsupportedEncodingException { + } + + public String getParameter(String name) { + return null; + } + + public Map getParameterMap() { + return null; + } + + public Enumeration getParameterNames() { + return dummyEnum; + } + + public String[] getParameterValues(String name) { + return null; + } + + public RequestDispatcher getRequestDispatcher(String path) { + return null; + } + + public String getAuthType() { + return null; + } + + public Cookie[] getCookies() { + return null; + } + + public long getDateHeader(String name) { + return -1L; + } + + public String getHeader(String name) { + return null; + } + + public Enumeration getHeaders(String name) { + return null; + } + + public Enumeration getHeaderNames() { + return null; + } + + public int getIntHeader(String name) { + return -1; + } + + public String getPathTranslated() { + return null; + } + + public String getRemoteUser() { + return null; + } + + public String getRequestedSessionId() { + return null; + } + + public String getRequestURI() { + return null; + } + + public StringBuffer getRequestURL() { + return null; + } + + public HttpSession getSession() { + return null; + } + + public HttpSession getSession(boolean create) { + return null; + } + + public String changeSessionId() { + return null; + } + + public boolean isRequestedSessionIdFromCookie() { + return false; + } + + public boolean isRequestedSessionIdFromURL() { + return false; + } + + public boolean isRequestedSessionIdFromUrl() { + return false; + } + + public boolean isRequestedSessionIdValid() { + return false; + } + + public void setRequestedSessionCookiePath(String cookiePath) { + } + + public boolean isUserInRole(String role) { + return false; + } + + public Principal getUserPrincipal() { + return null; + } + + public String getLocalAddr() { + return null; + } + + public String getLocalName() { + return null; + } + + public int getLocalPort() { + return -1; + } + + public int getRemotePort() { + return -1; + } + + public DispatcherType getDispatcherType() { + return null; + } + + public AsyncContext startAsync() throws IllegalStateException { + return null; + } + + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { + return null; + } + + public boolean isAsyncStarted() { + return false; + } + + public boolean isAsyncSupported() { + return false; + } + + public AsyncContext getAsyncContext() { + return null; + } + + public Collection getParts() { + return null; + } + + public Part getPart(String name) { + return null; + } + + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + return false; + } + + public void login(String username, String password) throws ServletException { + } + + public void logout() throws ServletException {} + + public T upgrade(Class handlerClass) { + return null; + } + + public ServletContext getServletContext() { + return null; + } + +} + From e720b7231a2d67123e13ac9a89bdef4e6ae93d0d Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 8 Jul 2024 15:14:59 +0530 Subject: [PATCH 011/122] Support for Solr HTTP2 Client with version 8.0.0-latest --- .../impl/HttpSolrServer_Instrumentation.java | 1 - .../solr-7.0.0/build.gradle | 2 +- .../client/solrj/impl/Http2SolrClient.java | 7 + .../solr-8.0.0/build.gradle | 29 ++++ .../impl/Http2SolrClient_Instrumentation.java | 114 ++++++++++++++++ .../impl/HttpSolrClient_Instrumentation.java | 125 ++++++++++++++++++ .../solr-9.0.0/build.gradle | 29 ++++ .../impl/Http2SolrClient_Instrumentation.java | 112 ++++++++++++++++ .../impl/HttpSolrClient_Instrumentation.java | 125 ++++++++++++++++++ settings.gradle | 2 + 10 files changed, 544 insertions(+), 2 deletions(-) create mode 100644 instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java create mode 100644 instrumentation-security/solr-8.0.0/build.gradle create mode 100644 instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java create mode 100644 instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java create mode 100644 instrumentation-security/solr-9.0.0/build.gradle create mode 100644 instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java create mode 100644 instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java diff --git a/instrumentation-security/solr-4.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrServer_Instrumentation.java b/instrumentation-security/solr-4.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrServer_Instrumentation.java index f7afcb950..d29563dc9 100644 --- a/instrumentation-security/solr-4.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrServer_Instrumentation.java +++ b/instrumentation-security/solr-4.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrServer_Instrumentation.java @@ -20,7 +20,6 @@ import org.apache.solr.client.solrj.ResponseParser; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.request.UpdateRequest; -import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.NamedList; diff --git a/instrumentation-security/solr-7.0.0/build.gradle b/instrumentation-security/solr-7.0.0/build.gradle index e416374a6..8eb1b68ee 100644 --- a/instrumentation-security/solr-7.0.0/build.gradle +++ b/instrumentation-security/solr-7.0.0/build.gradle @@ -18,7 +18,7 @@ jar { } verifyInstrumentation { - passesOnly 'org.apache.solr:solr-core:[7.0.0,)' + passesOnly 'org.apache.solr:solr-core:[7.0.0,8.0.0)' excludeRegex 'org.apache.solr:solr-core:.*(ALPHA|BETA)+$' } diff --git a/instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java b/instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java new file mode 100644 index 000000000..a6471858e --- /dev/null +++ b/instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java @@ -0,0 +1,7 @@ +package org.apache.solr.client.solrj.impl; + +import com.newrelic.api.agent.weaver.SkipIfPresent; + +@SkipIfPresent +public class Http2SolrClient { +} diff --git a/instrumentation-security/solr-8.0.0/build.gradle b/instrumentation-security/solr-8.0.0/build.gradle new file mode 100644 index 000000000..66396945a --- /dev/null +++ b/instrumentation-security/solr-8.0.0/build.gradle @@ -0,0 +1,29 @@ +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.lucene:lucene-core:4.0.0") + + implementation("org.apache.solr:solr-core:8.0.0") { + transitive = false + } + implementation("org.apache.solr:solr-solrj:8.0.0") { + transitive = false + } +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.solr-8.0.0' } +} + +verifyInstrumentation { + passesOnly 'org.apache.solr:solr-core:[8.0.0,9.0.0)' + + excludeRegex 'org.apache.solr:solr-core:.*(ALPHA|BETA)+$' +} + +site { + title 'Solr' + type 'Datastore' +} \ No newline at end of file diff --git a/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java b/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java new file mode 100644 index 000000000..26177ece3 --- /dev/null +++ b/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java @@ -0,0 +1,114 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.apache.solr.client.solrj.impl; +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.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.SolrDbOperation; +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 org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.request.UpdateRequest; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.Http2SolrClient") +public abstract class Http2SolrClient_Instrumentation { + + + public abstract String getBaseURL(); + + protected Http2SolrClient_Instrumentation(String serverBaseUrl, Http2SolrClient.Builder builder) { + //TODO report external URL + } + + public NamedList request(SolrRequest solrRequest, + String collection, + Http2SolrClient.OnComplete onComplete) throws IOException, SolrServerException { + boolean isLockAcquired = GenericHelper.acquireLockIfPossible("HTTP_SOLR_REQUEST-", solrRequest.hashCode()); + AbstractOperation operation = null; + if(isLockAcquired) { + operation = preprocessSolrRequest(solrRequest, "REQUEST"); + } + NamedList result; + try { + result = Weaver.callOriginal(); + } finally { + if(isLockAcquired) { + GenericHelper.releaseLock("HTTP_SOLR_REQUEST-", solrRequest.hashCode()); + } + } + registerExitOperation(isLockAcquired, operation); + return result; + } + + private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || GenericHelper.skipExistsEvent() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e){ + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + } + + private AbstractOperation preprocessSolrRequest(@SuppressWarnings({"rawtypes"})SolrRequest request, String methodName) { + try { + String collection = new URL(getBaseURL()).getPath(); + collection = collection.startsWith("/") ? collection.substring(1) : collection; + String method = request.getMethod().toString(); + String path = request.getPath(); + SolrParams solrParams = request.getParams(); + Map params = Collections.emptyMap(); + if(solrParams != null){ + params = SolrParams.toMap(solrParams.toNamedList()); + } + List documents = Collections.emptyList(); + if(request instanceof UpdateRequest) { + documents = ((UpdateRequest) request).getDocuments(); + } + SolrDbOperation solrDbOperation = new SolrDbOperation(this.getClass().getName(), methodName); + solrDbOperation.setCollection(collection); + solrDbOperation.setParams(params); + solrDbOperation.setDocuments(documents); + solrDbOperation.setConnectionURL(getBaseURL()); + solrDbOperation.setMethod(method); + solrDbOperation.setPath(path); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Solr request %s, %s, %s, %s, %s", collection, method, path, params, documents), this.getClass().getName()); + NewRelicSecurity.getAgent().registerOperation(solrDbOperation); + return solrDbOperation; + } catch (MalformedURLException e){ + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + return null; + } + +} diff --git a/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java b/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java new file mode 100644 index 000000000..bb8bfd0db --- /dev/null +++ b/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java @@ -0,0 +1,125 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.apache.solr.client.solrj.impl; +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.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.SolrDbOperation; +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 org.apache.solr.client.solrj.ResponseParser; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.request.UpdateRequest; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.HttpSolrClient") +public abstract class HttpSolrClient_Instrumentation { + + + public abstract String getBaseURL(); + + protected HttpSolrClient_Instrumentation(Builder builder) { + //TODO report external URL + } + + public NamedList request(@SuppressWarnings({"rawtypes"})final SolrRequest request, final ResponseParser processor, String collection) + throws SolrServerException, IOException { + boolean isLockAcquired = GenericHelper.acquireLockIfPossible("HTTP_SOLR_REQUEST-", request.hashCode()); + AbstractOperation operation = null; + if(isLockAcquired) { + operation = preprocessSolrRequest(request, "REQUEST"); + } + NamedList result; + try { + result = Weaver.callOriginal(); + } finally { + if(isLockAcquired) { + GenericHelper.releaseLock("HTTP_SOLR_REQUEST-", request.hashCode()); + } + } + registerExitOperation(isLockAcquired, operation); + return result; + } + + private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || GenericHelper.skipExistsEvent() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e){ + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + } + + private AbstractOperation preprocessSolrRequest(@SuppressWarnings({"rawtypes"})SolrRequest request, String methodName) { + try { + String collection = new URL(getBaseURL()).getPath(); + collection = collection.startsWith("/") ? collection.substring(1) : collection; + String method = request.getMethod().toString(); + String path = request.getPath(); + SolrParams solrParams = request.getParams(); + Map params = Collections.emptyMap(); + if(solrParams != null){ + params = SolrParams.toMap(solrParams.toNamedList()); + } + List documents = Collections.emptyList(); + if(request instanceof UpdateRequest) { + documents = ((UpdateRequest) request).getDocuments(); + } + SolrDbOperation solrDbOperation = new SolrDbOperation(this.getClass().getName(), methodName); + solrDbOperation.setCollection(collection); + solrDbOperation.setParams(params); + solrDbOperation.setDocuments(documents); + solrDbOperation.setConnectionURL(getBaseURL()); + solrDbOperation.setMethod(method); + solrDbOperation.setPath(path); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Solr request %s, %s, %s, %s, %s", collection, method, path, params, documents), this.getClass().getName()); + NewRelicSecurity.getAgent().registerOperation(solrDbOperation); + return solrDbOperation; + } catch (MalformedURLException e){ + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + return null; + } + + @Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.HttpSolrClient$Builder") + public static class Builder extends SolrClientBuilder { + protected String baseSolrUrl; + + @Override + public Builder getThis() { + return this; + } + } + +} diff --git a/instrumentation-security/solr-9.0.0/build.gradle b/instrumentation-security/solr-9.0.0/build.gradle new file mode 100644 index 000000000..1d8a0d532 --- /dev/null +++ b/instrumentation-security/solr-9.0.0/build.gradle @@ -0,0 +1,29 @@ +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.lucene:lucene-core:4.0.0") + + implementation("org.apache.solr:solr-core:8.0.0") { + transitive = false + } + implementation("org.apache.solr:solr-solrj:8.0.0") { + transitive = false + } +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.solr-9.0.0' } +} + +verifyInstrumentation { + passesOnly 'org.apache.solr:solr-core:[9.0.0,)' + exclude 'org.apache.solr:solr-core:[8.0.0,9.0.0)' + excludeRegex 'org.apache.solr:solr-core:.*(ALPHA|BETA)+$' +} + +site { + title 'Solr' + type 'Datastore' +} \ No newline at end of file diff --git a/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java b/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java new file mode 100644 index 000000000..ff9dbca8a --- /dev/null +++ b/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java @@ -0,0 +1,112 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.apache.solr.client.solrj.impl; +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.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.SolrDbOperation; +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 org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.request.UpdateRequest; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.Http2SolrClient") +public abstract class Http2SolrClient_Instrumentation { + + + public abstract String getBaseURL(); + + protected Http2SolrClient_Instrumentation(String serverBaseUrl, Http2SolrClient.Builder builder) { + //TODO report external URL + } + + public NamedList request(SolrRequest solrRequest, String collection) throws SolrServerException, IOException { + boolean isLockAcquired = GenericHelper.acquireLockIfPossible("HTTP_SOLR_REQUEST-", solrRequest.hashCode()); + AbstractOperation operation = null; + if(isLockAcquired) { + operation = preprocessSolrRequest(solrRequest, "REQUEST"); + } + NamedList result; + try { + result = Weaver.callOriginal(); + } finally { + if(isLockAcquired) { + GenericHelper.releaseLock("HTTP_SOLR_REQUEST-", solrRequest.hashCode()); + } + } + registerExitOperation(isLockAcquired, operation); + return result; + } + + private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || GenericHelper.skipExistsEvent() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e){ + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + } + + private AbstractOperation preprocessSolrRequest(@SuppressWarnings({"rawtypes"})SolrRequest request, String methodName) { + try { + String collection = new URL(getBaseURL()).getPath(); + collection = collection.startsWith("/") ? collection.substring(1) : collection; + String method = request.getMethod().toString(); + String path = request.getPath(); + SolrParams solrParams = request.getParams(); + Map params = Collections.emptyMap(); + if(solrParams != null){ + params = SolrParams.toMap(solrParams.toNamedList()); + } + List documents = Collections.emptyList(); + if(request instanceof UpdateRequest) { + documents = ((UpdateRequest) request).getDocuments(); + } + SolrDbOperation solrDbOperation = new SolrDbOperation(this.getClass().getName(), methodName); + solrDbOperation.setCollection(collection); + solrDbOperation.setParams(params); + solrDbOperation.setDocuments(documents); + solrDbOperation.setConnectionURL(getBaseURL()); + solrDbOperation.setMethod(method); + solrDbOperation.setPath(path); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Solr request %s, %s, %s, %s, %s", collection, method, path, params, documents), this.getClass().getName()); + NewRelicSecurity.getAgent().registerOperation(solrDbOperation); + return solrDbOperation; + } catch (MalformedURLException e){ + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + return null; + } + +} diff --git a/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java b/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java new file mode 100644 index 000000000..bb8bfd0db --- /dev/null +++ b/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java @@ -0,0 +1,125 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.apache.solr.client.solrj.impl; +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.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.SolrDbOperation; +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 org.apache.solr.client.solrj.ResponseParser; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.request.UpdateRequest; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.HttpSolrClient") +public abstract class HttpSolrClient_Instrumentation { + + + public abstract String getBaseURL(); + + protected HttpSolrClient_Instrumentation(Builder builder) { + //TODO report external URL + } + + public NamedList request(@SuppressWarnings({"rawtypes"})final SolrRequest request, final ResponseParser processor, String collection) + throws SolrServerException, IOException { + boolean isLockAcquired = GenericHelper.acquireLockIfPossible("HTTP_SOLR_REQUEST-", request.hashCode()); + AbstractOperation operation = null; + if(isLockAcquired) { + operation = preprocessSolrRequest(request, "REQUEST"); + } + NamedList result; + try { + result = Weaver.callOriginal(); + } finally { + if(isLockAcquired) { + GenericHelper.releaseLock("HTTP_SOLR_REQUEST-", request.hashCode()); + } + } + registerExitOperation(isLockAcquired, operation); + return result; + } + + private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || GenericHelper.skipExistsEvent() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e){ + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + } + + private AbstractOperation preprocessSolrRequest(@SuppressWarnings({"rawtypes"})SolrRequest request, String methodName) { + try { + String collection = new URL(getBaseURL()).getPath(); + collection = collection.startsWith("/") ? collection.substring(1) : collection; + String method = request.getMethod().toString(); + String path = request.getPath(); + SolrParams solrParams = request.getParams(); + Map params = Collections.emptyMap(); + if(solrParams != null){ + params = SolrParams.toMap(solrParams.toNamedList()); + } + List documents = Collections.emptyList(); + if(request instanceof UpdateRequest) { + documents = ((UpdateRequest) request).getDocuments(); + } + SolrDbOperation solrDbOperation = new SolrDbOperation(this.getClass().getName(), methodName); + solrDbOperation.setCollection(collection); + solrDbOperation.setParams(params); + solrDbOperation.setDocuments(documents); + solrDbOperation.setConnectionURL(getBaseURL()); + solrDbOperation.setMethod(method); + solrDbOperation.setPath(path); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Solr request %s, %s, %s, %s, %s", collection, method, path, params, documents), this.getClass().getName()); + NewRelicSecurity.getAgent().registerOperation(solrDbOperation); + return solrDbOperation; + } catch (MalformedURLException e){ + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + return null; + } + + @Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.HttpSolrClient$Builder") + public static class Builder extends SolrClientBuilder { + protected String baseSolrUrl; + + @Override + public Builder getThis() { + return this; + } + } + +} diff --git a/settings.gradle b/settings.gradle index 30b633a6d..6023999fd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -212,3 +212,5 @@ include 'instrumentation:jedis-2.7.1_2.7.2' include 'instrumentation:solr-4.0.0' include 'instrumentation:solr-5.0.0' include 'instrumentation:solr-7.0.0' +include 'instrumentation:solr-8.0.0' +include 'instrumentation:solr-9.0.0' From ddc2dbfb28b3f8c8cc0ee65fb51e75ec5f39d894 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 9 Jul 2024 21:36:14 +0530 Subject: [PATCH 012/122] Default Auth mechanism requires setting of property jdk.http.auth.tunneling.disabledSchemes --- .../intcodeagent/websocket/WSClient.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) 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 64f1ffcfd..d9ca223a7 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 @@ -181,16 +181,20 @@ private static Proxy proxyManager() { Proxy proxy = new Proxy(getProxyScheme(proxyScheme), new InetSocketAddress(proxyHost, proxyPort)); if (proxyUser != null && proxyPass != null) { - // This Sets the authenticator that will be used by - // the networking code when a proxy or an HTTP server asks for authentication. - // This can lead to potential leak of authentication info by the application itself. -// Authenticator.setDefault(new Authenticator() { -// @Override -// protected PasswordAuthentication getPasswordAuthentication() { -// return new PasswordAuthentication(proxyUser, proxyPass.toCharArray()); -// } -// }); -// logger.log(LogLevel.FINER, "Authenticated proxy using username and password", WSClient.class.getName()); + /** + * This Sets the authenticator that will be used by + * the networking code when a proxy or an HTTP server asks for authentication. + * This can lead to potential leak of authentication info by the application itself. + */ + // Requires System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); reference https://github.com/TooTallNate/Java-WebSocket/issues/1179#issuecomment-2184917604 + System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(proxyUser, proxyPass.toCharArray()); + } + }); + logger.log(LogLevel.FINER, "Authenticated proxy using username and password", WSClient.class.getName()); } logger.log(LogLevel.FINER, String.format("Proxy being used to connect with WSS %s", proxy), WSClient.class.getName()); return proxy; From b32f259f4f984778c477cda8dbbedcb8ab95e75d Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 15 Jul 2024 15:03:36 +0530 Subject: [PATCH 013/122] Schema for storing vertx routes --- .../security/schema/helper/VertxRoute.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/helper/VertxRoute.java diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/helper/VertxRoute.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/helper/VertxRoute.java new file mode 100644 index 000000000..bbd1625c2 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/helper/VertxRoute.java @@ -0,0 +1,83 @@ +package com.newrelic.api.agent.security.schema.helper; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +public class VertxRoute { + + private int routerHashCode; + private int routeHashCode; + private String path; + private String pattern; + private Set methods; + private String handlerName; + + public VertxRoute(int routerHashCode, int routeHashCode) { + this.routerHashCode = routerHashCode; + this.routeHashCode = routeHashCode; + this.methods = new HashSet<>(); + } + + public int getRouterHashCode() { + return routerHashCode; + } + + public void setRouterHashCode(int routerHashCode) { + this.routerHashCode = routerHashCode; + } + + public int getRouteHashCode() { + return routeHashCode; + } + + public void setRouteHashCode(int routeHashCode) { + this.routeHashCode = routeHashCode; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getPattern() { + return pattern; + } + + public void setPattern(String pattern) { + this.pattern = pattern; + } + + public Set getMethods() { + return methods; + } + + public void setMethods(Set methods) { + this.methods = methods; + } + + public String getHandlerName() { + return handlerName; + } + + public void setHandlerName(String handlerName) { + this.handlerName = handlerName; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof VertxRoute)) { + return false; + } + return Objects.equals(routerHashCode, ((VertxRoute) obj).routerHashCode) && + Objects.equals(routeHashCode, ((VertxRoute) obj).routeHashCode); + } + + @Override + public int hashCode() { + return Objects.hash(routerHashCode, routeHashCode); + } +} From e681228609e2d2705a7e5539ae0f2a950703b714 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 15 Jul 2024 17:29:04 +0530 Subject: [PATCH 014/122] API Endpoint detection support for vertx framework --- .../vertx-core-3.3.0/build.gradle | 5 +- .../core/http/HttpServer_Instrumentation.java | 28 ++++++++ .../vertx-core-3.4.0/build.gradle | 5 +- .../core/http/HttpServer_Instrumentation.java | 28 ++++++++ .../vertx-core-3.7.1/build.gradle | 5 +- .../core/http/HttpServer_Instrumentation.java | 28 ++++++++ .../vertx-core-4.0.0/build.gradle | 5 +- .../core/http/HttpServer_Instrumentation.java | 28 ++++++++ .../vertx/ext/web/Router_Instrumentation.java | 25 +++++++ .../web/impl/RouteImpl_Instrumentation.java | 61 +++++++++++++++- .../vertx/ext/web/Router_Instrumentation.java | 25 +++++++ .../web/impl/RouteImpl_Instrumentation.java | 61 ++++++++++++++++ .../web/impl/RouteImpl_Instrumentation.java | 70 +++++++++++++++++++ 13 files changed, 369 insertions(+), 5 deletions(-) create mode 100644 instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java create mode 100644 instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java create mode 100644 instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java create mode 100644 instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java create mode 100644 instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/Router_Instrumentation.java create mode 100644 instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/Router_Instrumentation.java create mode 100644 instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java diff --git a/instrumentation-security/vertx-core-3.3.0/build.gradle b/instrumentation-security/vertx-core-3.3.0/build.gradle index 3f9e79eca..bea94f57b 100644 --- a/instrumentation-security/vertx-core-3.3.0/build.gradle +++ b/instrumentation-security/vertx-core-3.3.0/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("io.vertx:vertx-core:3.3.0") + implementation("io.vertx:vertx-web:3.3.0") } jar { @@ -10,7 +11,9 @@ jar { } verifyInstrumentation { - passesOnly 'io.vertx:vertx-core:[3.3.0,3.4.0)' + passesOnly ('io.vertx:vertx-core:[3.3.0,3.4.0)') { + implementation("io.vertx:vertx-web:3.3.0") + } excludeRegex '.*(milestone|CR|Beta)[0-9]*' } diff --git a/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java b/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java new file mode 100644 index 000000000..1624dfcc6 --- /dev/null +++ b/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java @@ -0,0 +1,28 @@ +package io.vertx.core.http; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.VertxApiEndpointUtils; +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 io.vertx.core.Handler; +import io.vertx.ext.web.impl.RouterImpl; + +@Weave(originalName = "io.vertx.core.http.HttpServer", type = MatchType.Interface) +public class HttpServer_Instrumentation { + + public HttpServer_Instrumentation requestHandler(Handler handler){ + HttpServer_Instrumentation server = Weaver.callOriginal(); + try { + if (handler instanceof RouterImpl) { + VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); + } + } catch (Exception e){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, "VERTX-CORE-3.3.0", e.getMessage()), e, VertxApiEndpointUtils.class.getName()); + } + return server; + } + +} diff --git a/instrumentation-security/vertx-core-3.4.0/build.gradle b/instrumentation-security/vertx-core-3.4.0/build.gradle index 25d8d3d69..a65c8ff23 100644 --- a/instrumentation-security/vertx-core-3.4.0/build.gradle +++ b/instrumentation-security/vertx-core-3.4.0/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("io.vertx:vertx-core:3.4.0") + implementation("io.vertx:vertx-web:3.4.0") testImplementation('io.vertx:vertx-web-client:3.4.0') } @@ -11,7 +12,9 @@ jar { } verifyInstrumentation { - passesOnly 'io.vertx:vertx-core:[3.4.0,3.7.1)' + passesOnly ('io.vertx:vertx-core:[3.4.0,3.7.1)'){ + implementation("io.vertx:vertx-web:3.4.0") + } excludeRegex '.*CR[0-9]*' excludeRegex '.*-milestone[0-9]' excludeRegex '.*Beta[0-9]' diff --git a/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java b/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java new file mode 100644 index 000000000..bdea6e2c1 --- /dev/null +++ b/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java @@ -0,0 +1,28 @@ +package io.vertx.core.http; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.VertxApiEndpointUtils; +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 io.vertx.core.Handler; +import io.vertx.ext.web.impl.RouterImpl; + +@Weave(originalName = "io.vertx.core.http.HttpServer", type = MatchType.Interface) +public class HttpServer_Instrumentation { + + public HttpServer_Instrumentation requestHandler(Handler handler){ + HttpServer_Instrumentation server = Weaver.callOriginal(); + try { + if (handler instanceof RouterImpl) { + VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); + } + } catch (Exception e){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, "VERTX-CORE-3.4.0", e.getMessage()), e, VertxApiEndpointUtils.class.getName()); + } + return server; + } + +} diff --git a/instrumentation-security/vertx-core-3.7.1/build.gradle b/instrumentation-security/vertx-core-3.7.1/build.gradle index d5ee37175..3b1b8db62 100644 --- a/instrumentation-security/vertx-core-3.7.1/build.gradle +++ b/instrumentation-security/vertx-core-3.7.1/build.gradle @@ -9,11 +9,14 @@ dependencies { implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation("io.vertx:vertx-core:3.7.1") + implementation("io.vertx:vertx-web:3.7.1") testImplementation('io.vertx:vertx-web-client:3.7.1') } verifyInstrumentation { - passesOnly 'io.vertx:vertx-core:[3.7.1,4.0.0.Beta1)' + passesOnly ('io.vertx:vertx-core:[3.7.1,4.0.0.Beta1)') { + implementation('io.vertx:vertx-web:3.7.1') + } excludeRegex '.*CR[0-9]*' excludeRegex '.*-milestone[0-9]' } diff --git a/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java b/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java new file mode 100644 index 000000000..5dbf5d6a9 --- /dev/null +++ b/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java @@ -0,0 +1,28 @@ +package io.vertx.core.http; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.VertxApiEndpointUtils; +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 io.vertx.ext.web.impl.RouterImpl; +import io.vertx.core.Handler; + +@Weave(originalName = "io.vertx.core.http.HttpServer", type = MatchType.Interface) +public class HttpServer_Instrumentation { + + public HttpServer_Instrumentation requestHandler(Handler handler){ + HttpServer_Instrumentation server = Weaver.callOriginal(); + try { + if (handler instanceof RouterImpl) { + VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); + } + } catch (Exception e){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, "VERTX-CORE-3.7.1", e.getMessage()), e, VertxApiEndpointUtils.class.getName()); + } + return server; + } + +} diff --git a/instrumentation-security/vertx-core-4.0.0/build.gradle b/instrumentation-security/vertx-core-4.0.0/build.gradle index 50226b02a..8f8012a66 100644 --- a/instrumentation-security/vertx-core-4.0.0/build.gradle +++ b/instrumentation-security/vertx-core-4.0.0/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("io.vertx:vertx-core:4.0.0") + implementation("io.vertx:vertx-web:4.0.0") testImplementation('io.vertx:vertx-web-client:4.0.0') } @@ -13,7 +14,9 @@ jar { } verifyInstrumentation { - passesOnly 'io.vertx:vertx-core:[4.0.0,)' + passesOnly ('io.vertx:vertx-core:[4.0.0,)') { + implementation('io.vertx:vertx-web:4.0.0') + } excludeRegex '.*CR[0-9]*' excludeRegex '.*-milestone[0-9]' excludeRegex '.*Beta[0-9]' diff --git a/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java b/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java new file mode 100644 index 000000000..096589c04 --- /dev/null +++ b/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java @@ -0,0 +1,28 @@ +package io.vertx.core.http; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.VertxApiEndpointUtils; +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 io.vertx.core.Handler; +import io.vertx.ext.web.impl.RouterImpl; + + +@Weave(originalName = "io.vertx.core.http.HttpServer", type = MatchType.Interface) +public class HttpServer_Instrumentation { + + public HttpServer_Instrumentation requestHandler(Handler handler){ + HttpServer_Instrumentation server = Weaver.callOriginal(); + try { + if (handler instanceof RouterImpl) { + VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); + } + } catch (Exception e){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, "VERTX-CORE-4.0.0", e.getMessage()), e, VertxApiEndpointUtils.class.getName()); + } + return server; + } +} diff --git a/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/Router_Instrumentation.java b/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/Router_Instrumentation.java new file mode 100644 index 000000000..b89e88acc --- /dev/null +++ b/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/Router_Instrumentation.java @@ -0,0 +1,25 @@ +package io.vertx.ext.web; + +import com.newrelic.api.agent.security.instrumentation.helpers.ThreadLocalLockHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.VertxApiEndpointUtils; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +@Weave(originalName = "io.vertx.ext.web.Router", type = MatchType.Interface) +public class Router_Instrumentation { + + public Router_Instrumentation mountSubRouter(String mountPoint, Router subRouter) { + Router_Instrumentation result; + boolean isLockAcquired = ThreadLocalLockHelper.acquireLock(); + try { + result = Weaver.callOriginal(); + } finally { + if (isLockAcquired) { + ThreadLocalLockHelper.releaseLock(); + } + } + VertxApiEndpointUtils.getInstance().resolveSubRoutes(this.hashCode(), subRouter.hashCode(), mountPoint); + return result; + } +} diff --git a/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java b/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java index 9217471b8..249dcf1f1 100644 --- a/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java +++ b/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java @@ -1,15 +1,74 @@ package io.vertx.ext.web.impl; +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.VertxApiEndpointUtils; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; +import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; +import io.vertx.ext.web.Route; import io.vertx.ext.web.RoutingContext; +import java.util.regex.Pattern; + @Weave(originalName = "io.vertx.ext.web.impl.RouteImpl") -public class RouteImpl_Instrumentation { +public abstract class RouteImpl_Instrumentation { + + private final RouterImpl router = Weaver.callOriginal(); + + private String path = Weaver.callOriginal(); + + private Pattern pattern = Weaver.callOriginal(); + + RouteImpl_Instrumentation(RouterImpl router, int order){ + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, null, null); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, HttpMethod method, String path) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), path, null, method.name()); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, String path) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), path, null, null); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, HttpMethod method, String regex, boolean bregex) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, regex, method.name()); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, String regex, boolean bregex) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, regex, null); + } synchronized void handleContext(RoutingContext context) { ServletHelper.registerUserLevelCode("vertx-web"); Weaver.callOriginal(); } + + public synchronized Route method(HttpMethod method) { + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, null, method.name()); + return route; + } + + public synchronized Route path(String path) { + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), path, null, null); + return route; + } + + public synchronized Route pathRegex(String regex) { + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, regex, null); + return route; + } + + public synchronized Route handler(Handler contextHandler){ + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addHandlerClass(router.hashCode(), this.hashCode(), contextHandler.getClass().getName()); + return route; + } } diff --git a/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/Router_Instrumentation.java b/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/Router_Instrumentation.java new file mode 100644 index 000000000..6d788d82e --- /dev/null +++ b/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/Router_Instrumentation.java @@ -0,0 +1,25 @@ +package io.vertx.ext.web; + +import com.newrelic.api.agent.security.instrumentation.helpers.ThreadLocalLockHelper; +import com.newrelic.api.agent.security.instrumentation.helpers.VertxApiEndpointUtils; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +@Weave(originalName = "io.vertx.ext.web.Router", type = MatchType.Interface) +public class Router_Instrumentation { + + public Router_Instrumentation mountSubRouter(String mountPoint, Router subRouter) { + Router_Instrumentation result; + boolean isLockAcquired = ThreadLocalLockHelper.acquireLock(); + try { + result = Weaver.callOriginal(); + } finally { + if (isLockAcquired) { + ThreadLocalLockHelper.releaseLock(); + } + } + VertxApiEndpointUtils.getInstance().resolveSubRoutes(this.hashCode(), subRouter.hashCode(), mountPoint); + return result; + } +} \ No newline at end of file diff --git a/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java b/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java index f69d47e2d..a447b808b 100644 --- a/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java +++ b/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java @@ -1,14 +1,75 @@ package io.vertx.ext.web.impl; +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.VertxApiEndpointUtils; +import com.newrelic.api.agent.security.schema.Framework; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; +import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; +import io.vertx.ext.web.Route; +import io.vertx.ext.web.RoutingContext; + +import java.util.regex.Pattern; @Weave(originalName = "io.vertx.ext.web.impl.RouteImpl") public class RouteImpl_Instrumentation { + private final RouterImpl router = Weaver.callOriginal(); + + private String path = Weaver.callOriginal(); + + private Pattern pattern = Weaver.callOriginal(); + + RouteImpl_Instrumentation(RouterImpl router, int order){ + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, null, null); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, HttpMethod method, String path) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), path, null, method.name()); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, String path) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), path, null, null); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, HttpMethod method, String regex, boolean bregex) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, regex, method.name()); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, String regex, boolean bregex) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, regex, null); + } + void handleContext(RoutingContextImplBase context) { ServletHelper.registerUserLevelCode("vertx-web"); Weaver.callOriginal(); } + + public synchronized Route method(HttpMethod method) { + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, null, method.name()); + return route; + } + + public synchronized Route path(String path) { + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), path, null, null); + return route; + } + + public synchronized Route pathRegex(String regex) { + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, regex, null); + return route; + } + + public synchronized Route handler(Handler contextHandler){ + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addHandlerClass(router.hashCode(), this.hashCode(), contextHandler.getClass().getName()); + return route; + } } diff --git a/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java b/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java new file mode 100644 index 000000000..04026fe3c --- /dev/null +++ b/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java @@ -0,0 +1,70 @@ +package io.vertx.ext.web.impl; + +import com.newrelic.api.agent.security.instrumentation.helpers.VertxApiEndpointUtils; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; +import io.vertx.ext.web.Route; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; + +@Weave(originalName = "io.vertx.ext.web.impl.RouteImpl", type = MatchType.ExactClass) +public class RouteImpl_Instrumentation { + + private final RouterImpl router = Weaver.callOriginal(); + + private volatile RouteState state = Weaver.callOriginal(); + + RouteImpl_Instrumentation(RouterImpl router, int order){ + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, null, null); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, HttpMethod method, String path) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), path, null, method.name()); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, String path) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), path, null, null); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, HttpMethod method, String regex, boolean bregex) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, regex, method.name()); + } + + RouteImpl_Instrumentation(RouterImpl router, int order, String regex, boolean bregex) { + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, regex, null); + } + + public synchronized Route method(HttpMethod method) { + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, null, method.name()); + return route; + } + + public synchronized Route path(String path) { + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), path, null, null); + return route; + } + + public synchronized Route pathRegex(String regex) { + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addRouteImpl(router.hashCode(), this.hashCode(), null, regex, null); + return route; + } + + public synchronized Route handler(Handler contextHandler){ + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().addHandlerClass(router.hashCode(), this.hashCode(), contextHandler.getClass().getName()); + return route; + } + + public synchronized Route subRouter(Router subRouter) { + Route route = Weaver.callOriginal(); + VertxApiEndpointUtils.getInstance().removeRouteImpl(router.hashCode(), this.hashCode()); + VertxApiEndpointUtils.getInstance().resolveSubRoutes(router.hashCode(), subRouter.hashCode(), VertxApiEndpointUtils.getInstance().getPath(state.getPath(), state.getPattern())); + return route; + } +} From 8aa3e7c9c2505788aa4202d26eabbcf76fcd3110 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 15 Jul 2024 17:30:44 +0530 Subject: [PATCH 015/122] Utility for detecting vertx API Endpoints --- .../helpers/VertxApiEndpointUtils.java | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java new file mode 100644 index 000000000..ec4b704a7 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java @@ -0,0 +1,154 @@ +package com.newrelic.api.agent.security.instrumentation.helpers; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.ApplicationURLMapping; +import com.newrelic.api.agent.security.schema.Framework; +import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.helper.VertxRoute; +import com.newrelic.api.agent.security.utils.logging.LogLevel; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Pattern; + +public class VertxApiEndpointUtils { + + private static final class InstanceHolder { + static final VertxApiEndpointUtils instance = new VertxApiEndpointUtils(); + } + private final String VERTX_FRAMEWORK = "VERTX-FRAMEWORK"; + + public static VertxApiEndpointUtils getInstance() { + return InstanceHolder.instance; + } + + private VertxApiEndpointUtils() {} + + private final Map> routes = new ConcurrentHashMap<>(); + + public void clear(){ + routes.clear(); + } + + private void addRouteImpl(int routerHashCode, int routeHashCode) throws Exception { + boolean isLockAcquired = ThreadLocalLockHelper.acquireLock(); + try { + if (isLockAcquired) { + VertxRoute route = new VertxRoute(routerHashCode, routeHashCode); + if (!routes.containsKey(routerHashCode)) { + routes.put(routerHashCode, new ConcurrentHashMap<>()); + } + routes.get(routerHashCode).put(route.hashCode(), route); + } + } finally { + if (isLockAcquired) { + ThreadLocalLockHelper.releaseLock(); + } + } + } + + public void addRouteImpl(int routerHashCode, int routeHashCode, String path, String pattern, String method){ + try { + addRouteImpl(routerHashCode, routeHashCode); + if (!routes.containsKey(routerHashCode)){ + return; + } + VertxRoute route = routes.get(routerHashCode).get(Objects.hash(routerHashCode, routeHashCode)); + if (route == null){ + return; + } + if (path != null) { + route.setPath(path); + } + if (pattern != null) { + route.setPattern(pattern); + } + if (method != null) { + route.getMethods().add(method); + } + } catch (Exception e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, VERTX_FRAMEWORK, e.getMessage()), e, VertxApiEndpointUtils.class.getName()); + } + } + + public void addHandlerClass(int routerHashCode, int routeHashCode, String handlerName){ + try { + if (!routes.containsKey(routerHashCode)){ + return; + } + VertxRoute route = routes.get(routerHashCode).get(Objects.hash(routerHashCode, routeHashCode)); + if (route == null || !Objects.isNull(route.getHandlerName())){ + return; + } + route.setHandlerName(handlerName); + } catch (Exception e) {} + } + + public void resolveSubRoutes(int parentRouterHashCode, int childRouterHashCode, String path){ + try { + if (path == null || !routes.containsKey(childRouterHashCode) || !routes.containsKey(parentRouterHashCode)){ + return; + } + + for (Map.Entry vertxRoute : routes.get(childRouterHashCode).entrySet()) { + VertxRoute route = vertxRoute.getValue(); + if (StringUtils.equalsAny(route.getHandlerName(), "io.vertx.ext.web.handler.impl.BodyHandlerImpl", "io.vertx.ext.web.handler.BodyHandler")){ + continue; + } + String subRoutePath = getPath(route.getPath(), route.getPattern()); + route.setPath(StringUtils.removeEnd(path, StringUtils.SEPARATOR) + StringUtils.prependIfMissing(subRoutePath, StringUtils.SEPARATOR)); + route.setRouterHashCode(parentRouterHashCode); + routes.get(parentRouterHashCode).put(route.hashCode(), route); + } + } catch (Exception e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, VERTX_FRAMEWORK, e.getMessage()), e, VertxApiEndpointUtils.class.getName()); + } + } + + public void generateAPIEndpoints(int routerHashCode){ + if (!routes.containsKey(routerHashCode)){ + return; + } + for (Map.Entry vertxRoute : routes.get(routerHashCode).entrySet()){ + VertxRoute routeImpl = vertxRoute.getValue(); + String handlerName = routeImpl.getHandlerName(); + if (StringUtils.equalsAny(handlerName, "io.vertx.ext.web.handler.impl.BodyHandlerImpl", "io.vertx.ext.web.handler.BodyHandler")){ + continue; + } + if (handlerName != null){ + handlerName = StringUtils.substringBefore(routeImpl.getHandlerName(), StringUtils.SEPARATOR); + } + if (routeImpl.getMethods().isEmpty()){ + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, getPath(routeImpl.getPath(), routeImpl.getPattern()), handlerName)); + } + for (String method : routeImpl.getMethods()) { + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(method, getPath(routeImpl.getPath(), routeImpl.getPattern()), handlerName)); + } + } + } + + public void removeRouteImpl(int routerHashCode, int routeHashCode){ + try { + if (routes.containsKey(routerHashCode) && routes.get(routerHashCode).containsKey(routeHashCode)){ + VertxRoute route = routes.get(routerHashCode).remove(routeHashCode); + if (route != null && !URLMappingsHelper.getApplicationURLMappings().isEmpty()){ + URLMappingsHelper.getApplicationURLMappings().remove(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, getPath(route.getPath(), route.getPattern()))); + } + } + } catch (Exception e) {} + } + + public String getPath(String path, Object pattern) { + if (path != null){ + return path; + } + if (pattern instanceof Pattern) { + return ((Pattern) pattern).pattern(); + } + if (pattern instanceof String) { + return (String) pattern; + } + return URLMappingsHelper.subResourceSegment; + } +} From 2c3015c6973b037b45aacf21201312eebc457e8f Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 15 Jul 2024 18:15:32 +0530 Subject: [PATCH 016/122] NR-291517: Route detection support for vertx framework --- .../web/impl/RouteImpl_Instrumentation.java | 5 +++++ .../web/impl/RouteImpl_Instrumentation.java | 5 +++++ .../web/impl/RouteState_Instrumentation.java | 20 +++++++++++++++++++ .../helpers/VertxApiEndpointUtils.java | 11 ++++++++++ 4 files changed, 41 insertions(+) diff --git a/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java b/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java index 249dcf1f1..0a160d421 100644 --- a/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java +++ b/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java @@ -44,6 +44,11 @@ public abstract class RouteImpl_Instrumentation { } synchronized void handleContext(RoutingContext context) { + try { + VertxApiEndpointUtils.getInstance().routeDetection(path, pattern); + } catch (Exception e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, "VERTX-WEB-3.2.0", e.getMessage()), e, this.getClass().getName()); + } ServletHelper.registerUserLevelCode("vertx-web"); Weaver.callOriginal(); } diff --git a/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java b/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java index a447b808b..6a28d9f35 100644 --- a/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java +++ b/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java @@ -45,6 +45,11 @@ public class RouteImpl_Instrumentation { } void handleContext(RoutingContextImplBase context) { + try { + VertxApiEndpointUtils.getInstance().routeDetection(path, pattern); + } catch (Exception e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, "VERTX-WEB-3.5.1", e.getMessage()), e, this.getClass().getName()); + } ServletHelper.registerUserLevelCode("vertx-web"); Weaver.callOriginal(); } diff --git a/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteState_Instrumentation.java b/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteState_Instrumentation.java index acb7d0c98..6c451c238 100644 --- a/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteState_Instrumentation.java +++ b/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteState_Instrumentation.java @@ -1,13 +1,33 @@ package io.vertx.ext.web.impl; +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.VertxApiEndpointUtils; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; +import java.util.regex.Pattern; + @Weave(originalName = "io.vertx.ext.web.impl.RouteState") abstract class RouteState_Instrumentation { + void handleContext(RoutingContextImplBase context){ + try { + VertxApiEndpointUtils.getInstance().routeDetection(getPath(), getPattern()); + } catch (Exception e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, "VERTX-WEB-3.8.3", e.getMessage()), e, this.getClass().getName()); + } ServletHelper.registerUserLevelCode("vertx-web"); Weaver.callOriginal(); } + + public String getPath() { + return Weaver.callOriginal(); + } + + public Pattern getPattern() { + return Weaver.callOriginal(); + } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java index ec4b704a7..4922194b1 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java @@ -151,4 +151,15 @@ public String getPath(String path, Object pattern) { } return URLMappingsHelper.subResourceSegment; } + + public void routeDetection(String path, Pattern pattern) { + if (NewRelicSecurity.isHookProcessingActive()){ + if (path != null){ + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(path); + } else if (pattern != null){ + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(pattern.pattern()); + } + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.VERTX); + } + } } From b8886b6d900bcfd88ba75b0cede2822d45162256 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 16 Jul 2024 14:19:47 +0530 Subject: [PATCH 017/122] Support Route detection for vertx sub-routes --- .../instrumentation/helpers/VertxApiEndpointUtils.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java index 4922194b1..5c0d58823 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java @@ -154,10 +154,11 @@ public String getPath(String path, Object pattern) { public void routeDetection(String path, Pattern pattern) { if (NewRelicSecurity.isHookProcessingActive()){ + boolean isAlreadyServlet = Objects.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().getFramework(), Framework.SERVLET.name()); if (path != null){ - NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(path); + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(path, isAlreadyServlet); } else if (pattern != null){ - NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(pattern.pattern()); + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(pattern.pattern(), isAlreadyServlet); } NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.VERTX); } From 969ad064d899598757f48a6915efdc6263066c42 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 16 Jul 2024 15:35:41 +0530 Subject: [PATCH 018/122] Bump jsonVersion to 1.2.4 due to NR-290456 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8e99a4eca..dec247fde 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # The agent version. agentVersion=1.4.0 -jsonVersion=1.2.3 +jsonVersion=1.2.4 # Updated exposed NR APM API version. nrAPIVersion=8.12.0 From 67f2f03c1737ea7e1947ece65fff923441f3dfe3 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 16 Jul 2024 17:25:21 +0530 Subject: [PATCH 019/122] Cleanup vertx-routes after detecting API endpoints --- .../instrumentation/helpers/VertxApiEndpointUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java index 5c0d58823..7dbf60ca1 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java @@ -27,7 +27,7 @@ private VertxApiEndpointUtils() {} private final Map> routes = new ConcurrentHashMap<>(); - public void clear(){ + private void clear(){ routes.clear(); } @@ -126,6 +126,7 @@ public void generateAPIEndpoints(int routerHashCode){ URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(method, getPath(routeImpl.getPath(), routeImpl.getPattern()), handlerName)); } } + clear(); } public void removeRouteImpl(int routerHashCode, int routeHashCode){ From 2525d98d1d74cb944f10d5347940964665847019 Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Wed, 17 Jul 2024 10:52:11 +0530 Subject: [PATCH 020/122] fix for NR-232603 (#281) Fix for incorrect API Endpoints detected in case of sub-resource for RestEasy Framework --- .../resteasy2/RestEasyHelper.java | 24 +++++++++++---- .../util/GetRestful_Instrumentation.java | 29 +++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 instrumentation-security/resteasy-2.2/src/main/java/org/jboss/resteasy/util/GetRestful_Instrumentation.java diff --git a/instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java b/instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java index b7f94a8c6..ab9e52176 100644 --- a/instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java +++ b/instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java @@ -6,19 +6,30 @@ import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.StringUtils; import com.newrelic.api.agent.security.utils.logging.LogLevel; +import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import org.jboss.resteasy.core.ResourceInvoker; import org.jboss.resteasy.core.ResourceLocator; import org.jboss.resteasy.core.ResourceMethod; +import java.util.Collections; +import java.util.List; + public class RestEasyHelper { - private static final String WILDCARD = "*"; public static final String RESTEASY_22 = "RESTEASY-2.2"; - public static final String ROUTE_DETECTION_COMPLETED = "ROUTE_DETECTION_COMPLETED"; + public static final String RESTEASY_SUB_RESOURCE_LIST = "SUB_RESOURCE_LIST"; public static void gatherUrlMappings(String path, ResourceInvoker invoker) { try{ + List subResourceList = Collections.emptyList(); + if (NewRelicSecurity.isHookProcessingActive()) { + subResourceList = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(RESTEASY_SUB_RESOURCE_LIST, List.class); + } if(invoker instanceof ResourceMethod) { ResourceMethod methodInvoker = (ResourceMethod) invoker; + if (subResourceList != null && !subResourceList.isEmpty() && subResourceList.contains(methodInvoker.getResourceClass().getName())){ + return; + } String handler = methodInvoker.getResourceClass().getName(); for (String httpMethod: methodInvoker.getHttpMethods()){ @@ -28,13 +39,16 @@ public static void gatherUrlMappings(String path, ResourceInvoker invoker) { // case of SubResources else if(invoker instanceof ResourceLocator) { ResourceLocator locatorInvoker = (ResourceLocator) invoker; + if (subResourceList != null && !subResourceList.isEmpty() && subResourceList.contains(locatorInvoker.getMethod().getDeclaringClass().getName())){ + return; + } String handler = locatorInvoker.getMethod().getDeclaringClass().getName(); - String finalPath = StringUtils.appendIfMissing(path, StringUtils.SEPARATOR) + WILDCARD; + String finalPath = StringUtils.appendIfMissing(path, StringUtils.SEPARATOR) + URLMappingsHelper.WILDCARD; - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(WILDCARD, finalPath, handler)); + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(URLMappingsHelper.WILDCARD, finalPath, handler)); } } catch (Exception ignored){ - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, RESTEASY_22, ignored.getMessage()), ignored, RestEasyHelper.class.getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, RESTEASY_22, ignored.getMessage()), ignored, RestEasyHelper.class.getName()); } } } diff --git a/instrumentation-security/resteasy-2.2/src/main/java/org/jboss/resteasy/util/GetRestful_Instrumentation.java b/instrumentation-security/resteasy-2.2/src/main/java/org/jboss/resteasy/util/GetRestful_Instrumentation.java new file mode 100644 index 000000000..53fbadcf7 --- /dev/null +++ b/instrumentation-security/resteasy-2.2/src/main/java/org/jboss/resteasy/util/GetRestful_Instrumentation.java @@ -0,0 +1,29 @@ +package org.jboss.resteasy.util; + +import com.newrelic.agent.security.instrumentation.resteasy2.RestEasyHelper; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.SecurityMetaData; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; + +import java.util.ArrayList; +import java.util.List; + +@Weave(originalName = "org.jboss.resteasy.util.GetRestful") +public class GetRestful_Instrumentation { + + private static boolean hasJAXRSAnnotations(Class c){ + boolean result = Weaver.callOriginal(); + if (NewRelicSecurity.isHookProcessingActive() && Boolean.TRUE.equals(result)){ + SecurityMetaData metaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + List subResourceList = metaData.getCustomAttribute(RestEasyHelper.RESTEASY_SUB_RESOURCE_LIST, List.class); + if (subResourceList == null) { + subResourceList = new ArrayList<>(); + } + subResourceList.add(c.getName()); + metaData.addCustomAttribute(RestEasyHelper.RESTEASY_SUB_RESOURCE_LIST, subResourceList); + } + return result; + } + +} From fce54dd377b9f98cf5966df6250abc4212ec3f4a Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Wed, 17 Jul 2024 10:53:26 +0530 Subject: [PATCH 021/122] [NR-278202] Fix for handler detection for Play Framework API Endpoint Support (#285) * Fix for NR-251469 Fixed detection of handler class for play framework API Endpoint Support * Update Play Framework Unit tests due to fix in handler class (NR-251469) --- .../play2_13/GeneratedRouter_Instrumentation.scala | 5 +++-- .../instrumentation/play2_7/APIEndpointTest.java | 10 +++++----- .../play24/GeneratedRouter_Instrumentation.scala | 5 +++-- .../play26/GeneratedRouter_Instrumentation.scala | 5 +++-- .../instrumentation/play26/APIEndpointTest.java | 10 +++++----- .../api/agent/security/schema/StringUtils.java | 4 ++++ 6 files changed, 23 insertions(+), 16 deletions(-) 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 index 2bddaae88..4dabe9884 100644 --- 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 @@ -1,7 +1,7 @@ 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.security.schema.{ApplicationURLMapping, StringUtils} import com.newrelic.api.agent.weaver.{MatchType, Weave, Weaver} import play.api.routing.HandlerDef import play.core.routing.{HandlerInvoker, HandlerInvokerFactory} @@ -24,7 +24,8 @@ abstract class GeneratedRouter_Instrumentation { val iterator = documentation.iterator while (iterator.hasNext) { val doc = iterator.next - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(doc._1, doc._2, doc._3)) + val handler = StringUtils.substringBeforeLast(doc._3, StringUtils.DOT_DELIMITER) + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(doc._1, doc._2, handler)) } } } 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 index ddf7bd9fd..d5fd9cb5c 100644 --- 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 @@ -41,11 +41,11 @@ public class APIEndpointTest { @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"); + expectedMappings.put("/hello", SimpleJavaController.class.getName()); + expectedMappings.put("/scalaHello", SimpleScalaController.class.getName()); + expectedMappings.put("/post", SimpleJavaController.class.getName()); + expectedMappings.put("/index", SimpleJavaController.class.getName()); + expectedMappings.put("/simple", SimpleJavaController.class.getName()); } @Test 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 index b0d071e24..3a69e0ce6 100644 --- 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 @@ -1,7 +1,7 @@ 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.security.schema.{ApplicationURLMapping, StringUtils} import com.newrelic.api.agent.weaver.{MatchType, Weave, Weaver} import play.core.routing.{HandlerDef, HandlerInvoker} @@ -22,7 +22,8 @@ abstract class GeneratedRouter_Instrumentation { val iterator = documentation.iterator while (iterator.hasNext) { val doc = iterator.next - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(doc._1, doc._2, doc._3)) + val handler = StringUtils.substringBeforeLast(doc._3, StringUtils.DOT_DELIMITER) + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(doc._1, doc._2, handler)) } } } 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 index 079fae659..3d67607aa 100644 --- 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 @@ -1,7 +1,7 @@ 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.security.schema.{ApplicationURLMapping, StringUtils} import com.newrelic.api.agent.weaver.{MatchType, Weave, Weaver} import play.api.routing.HandlerDef import play.core.routing.HandlerInvoker @@ -23,7 +23,8 @@ abstract class GeneratedRouter_Instrumentation { val iterator = documentation.iterator while (iterator.hasNext) { val doc = iterator.next - URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(doc._1, doc._2, doc._3)) + val handler = StringUtils.substringBeforeLast(doc._3, StringUtils.DOT_DELIMITER) + URLMappingsHelper.addApplicationURLMapping(new ApplicationURLMapping(doc._1, doc._2, handler)) } } } 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 index 04b364d3a..c6bf41f71 100644 --- 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 @@ -42,11 +42,11 @@ public class APIEndpointTest { @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"); + expectedMappings.put("/hello", SimpleJavaController.class.getName()); + expectedMappings.put("/scalaHello", SimpleScalaController.class.getName()); + expectedMappings.put("/post", SimpleJavaController.class.getName()); + expectedMappings.put("/index", SimpleJavaController.class.getName()); + expectedMappings.put("/simple", SimpleJavaController.class.getName()); } @Test 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 82808436d..e9f8e89b3 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 @@ -12,8 +12,12 @@ public class StringUtils { public static final String LF = "\n"; public static final int INDEX_NOT_FOUND = -1; public static final String COMMA_DELIMETER = ","; + + public static final String DOT_DELIMITER = "."; + public static final String SEPARATOR = "/"; + /** *

Checks if a CharSequence is not empty (""), not null and not whitespace only.

* From 9408f77b96f60fefd4f740cea451f5df1102c878 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 17 Jul 2024 14:06:59 +0530 Subject: [PATCH 022/122] Bump jsonVersion to 1.2.5 due to Secure cookie schema update Co-authored-by: Lovesh Baya --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f84600a61..9c99fae93 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # The agent version. agentVersion=1.3.1 -jsonVersion=1.2.1 +jsonVersion=1.2.5 # Updated exposed NR APM API version. nrAPIVersion=8.12.0 From 8ddb98da9f19c7ad9543136c0149f1af64edea25 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 17 Jul 2024 17:19:13 +0530 Subject: [PATCH 023/122] Fix stacktrace in case of SecureCookie Operation Co-authored-by: Lovesh Baya --- .../src/main/java/com/newrelic/api/agent/security/Agent.java | 3 +++ 1 file changed, 3 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 20251b010..8bb8f4bff 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 @@ -12,6 +12,7 @@ import com.newrelic.agent.security.intcodeagent.models.javaagent.*; import com.newrelic.agent.security.intcodeagent.utils.EncryptorUtils; import com.newrelic.api.agent.security.instrumentation.helpers.*; +import com.newrelic.api.agent.security.schema.operation.SecureCookieOperationSet; 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; @@ -276,6 +277,8 @@ public void registerOperation(AbstractOperation operation) { if (operation instanceof RXSSOperation) { operation.setStackTrace(securityMetaData.getMetaData().getServiceTrace()); securityMetaData.addCustomAttribute("RXSS_PROCESSED", true); + } else if (operation instanceof SecureCookieOperationSet) { + operation.setStackTrace(securityMetaData.getMetaData().getServiceTrace()); } else { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); operation.setStackTrace(Arrays.copyOfRange(trace, securityMetaData.getMetaData().getFromJumpRequiredInStackTrace(), trace.length)); From 42b6cbb311d356027e2a0b6c225bd67e0dbf7019 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 18 Jul 2024 09:50:21 +0530 Subject: [PATCH 024/122] Handle Boolean values for config log_level --- .../java/com/newrelic/agent/security/AgentConfig.java | 9 ++++++--- .../com/newrelic/agent/security/util/IUtilConstants.java | 2 ++ 2 files changed, 8 insertions(+), 3 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 af043606f..8f6aa1e76 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 @@ -88,9 +88,12 @@ private String applyRequiredGroup() { } private String applyRequiredLogLevel() { - String logLevel = IUtilConstants.INFO; - if (StringUtils.isNotBlank(NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_LOG_LEVEL))) { - logLevel = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_LOG_LEVEL); + String logLevel; + Object value = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_LOG_LEVEL); + if(value instanceof Boolean) { + logLevel = IUtilConstants.OFF; + } else { + logLevel = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_LOG_LEVEL, IUtilConstants.INFO); } try { 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 8764c0b62..aa39bd9b4 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 @@ -8,6 +8,7 @@ public interface IUtilConstants { String IAST = "IAST"; String GROUP_NAME = "group-name"; String INFO = "INFO"; + String OFF = "OFF"; String K_2_LOG_LEVEL = "K2_LOG_LEVEL"; String NR_LOG_LEVEL = "log_level"; String LOG_LEVEL = "log-level"; @@ -40,4 +41,5 @@ public interface IUtilConstants { String APPLICATION_TMP_DIRECTORY = "APPLICATION_TMP_DIRECTORY"; String JAVA_IO_TMPDIR = "java.io.tmpdir"; + } From 86fc56ec654cf783cbaca3d9ceedb28dcfc37480 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 18 Jul 2024 20:20:16 +0530 Subject: [PATCH 025/122] code fix --- .../agent/security/instrumentation/resteasy2/RestEasyHelper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java b/instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java index ab9e52176..43efac8a5 100644 --- a/instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java +++ b/instrumentation-security/resteasy-2.2/src/main/java/com/newrelic/agent/security/instrumentation/resteasy2/RestEasyHelper.java @@ -18,6 +18,7 @@ public class RestEasyHelper { public static final String RESTEASY_22 = "RESTEASY-2.2"; public static final String RESTEASY_SUB_RESOURCE_LIST = "SUB_RESOURCE_LIST"; + public static final String ROUTE_DETECTION_COMPLETED = "ROUTE_DETECTION_COMPLETED"; public static void gatherUrlMappings(String path, ResourceInvoker invoker) { try{ From 820be13d2819af2bf148969cf27f6c4f09d3a4c3 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 19 Jul 2024 17:00:55 +0530 Subject: [PATCH 026/122] add csec prefix to all instrumentation jars --- instrumentation-security/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation-security/build.gradle b/instrumentation-security/build.gradle index bd278a624..e4d65007e 100644 --- a/instrumentation-security/build.gradle +++ b/instrumentation-security/build.gradle @@ -23,6 +23,7 @@ subprojects { } jar { + archiveBaseName = "csec-${archiveBaseName.getOrNull()}" manifest { attributes 'Implementation-Vendor': 'New Relic', 'Implementation-Version': project.version } From 34d1d81b08fac491d4be4ddc2bcc93f7754ddc72 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 23 Jul 2024 17:28:19 +0530 Subject: [PATCH 027/122] Update solr-5.0.0 instrumentation hook --- .../solr/client/solrj/impl/HttpSolrClient_Instrumentation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java b/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java index 36545b366..88551b22e 100644 --- a/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java +++ b/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java @@ -40,7 +40,7 @@ public HttpSolrClient_Instrumentation(String baseURL, HttpClient client, Respons //TODO report external URL } - public NamedList request(final SolrRequest request, final ResponseParser processor) { + public NamedList request(final SolrRequest request, final ResponseParser processor, String collection) { boolean isLockAcquired = GenericHelper.acquireLockIfPossible("HTTP_SOLR_REQUEST-", request.hashCode()); AbstractOperation operation = null; if(isLockAcquired) { From da1ccf7ab7a50dcfe3725a58335dccd86a5fd95f Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 23 Jul 2024 17:45:31 +0530 Subject: [PATCH 028/122] Update solr build.gradle --- instrumentation-security/solr-9.0.0/build.gradle | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/instrumentation-security/solr-9.0.0/build.gradle b/instrumentation-security/solr-9.0.0/build.gradle index 1d8a0d532..4d68d4b8b 100644 --- a/instrumentation-security/solr-9.0.0/build.gradle +++ b/instrumentation-security/solr-9.0.0/build.gradle @@ -5,10 +5,10 @@ dependencies { implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation("org.apache.lucene:lucene-core:4.0.0") - implementation("org.apache.solr:solr-core:8.0.0") { + implementation("org.apache.solr:solr-core:9.0.0") { transitive = false } - implementation("org.apache.solr:solr-solrj:8.0.0") { + implementation("org.apache.solr:solr-solrj:9.0.0") { transitive = false } } @@ -17,6 +17,12 @@ jar { manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.solr-9.0.0' } } +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + } +} + verifyInstrumentation { passesOnly 'org.apache.solr:solr-core:[9.0.0,)' exclude 'org.apache.solr:solr-core:[8.0.0,9.0.0)' From b660e984912b9d60e1568ef15fdc4a87d403a097 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 23 Jul 2024 21:47:06 +0530 Subject: [PATCH 029/122] Add instrumentation support for solr-5.0.0 and 5.1.0 Co-authored-by: Lovesh Baya --- .../solr-5.0.0/build.gradle | 2 +- .../impl/HttpSolrClient_Instrumentation.java | 14 +-- .../apache/solr/handler/StreamHandler.java | 7 ++ .../solr-5.1.0/build.gradle | 32 +++++ .../impl/HttpSolrClient_Instrumentation.java | 111 ++++++++++++++++++ 5 files changed, 157 insertions(+), 9 deletions(-) create mode 100644 instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/handler/StreamHandler.java create mode 100644 instrumentation-security/solr-5.1.0/build.gradle create mode 100644 instrumentation-security/solr-5.1.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java diff --git a/instrumentation-security/solr-5.0.0/build.gradle b/instrumentation-security/solr-5.0.0/build.gradle index 236ad5a39..e31bd3530 100644 --- a/instrumentation-security/solr-5.0.0/build.gradle +++ b/instrumentation-security/solr-5.0.0/build.gradle @@ -21,7 +21,7 @@ jar { } verifyInstrumentation { - passesOnly 'org.apache.solr:solr-core:[5.0.0,7.0.0)' + passesOnly 'org.apache.solr:solr-core:[5.0.0,5.1.0)' excludeRegex 'org.apache.solr:solr-core:.*(ALPHA|BETA)+$' } diff --git a/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java b/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java index 88551b22e..8d7596c8d 100644 --- a/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java +++ b/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java @@ -6,7 +6,6 @@ */ package org.apache.solr.client.solrj.impl; -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.schema.AbstractOperation; @@ -29,7 +28,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.logging.Level; @Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.HttpSolrClient") public abstract class HttpSolrClient_Instrumentation { @@ -40,7 +38,7 @@ public HttpSolrClient_Instrumentation(String baseURL, HttpClient client, Respons //TODO report external URL } - public NamedList request(final SolrRequest request, final ResponseParser processor, String collection) { + public NamedList request(final SolrRequest request, final ResponseParser processor) { boolean isLockAcquired = GenericHelper.acquireLockIfPossible("HTTP_SOLR_REQUEST-", request.hashCode()); AbstractOperation operation = null; if(isLockAcquired) { @@ -97,15 +95,15 @@ private AbstractOperation preprocessSolrRequest(SolrRequest request, String meth NewRelicSecurity.getAgent().registerOperation(solrDbOperation); return solrDbOperation; } catch (MalformedURLException e){ - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_5.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_5.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_5.0.0", e.getMessage()), e, this.getClass().getName()); throw e; } - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_5.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_5.0.0", e.getMessage()), e, this.getClass().getName()); } return null; } diff --git a/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/handler/StreamHandler.java b/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/handler/StreamHandler.java new file mode 100644 index 000000000..a8ada0ab6 --- /dev/null +++ b/instrumentation-security/solr-5.0.0/src/main/java/org/apache/solr/handler/StreamHandler.java @@ -0,0 +1,7 @@ +package org.apache.solr.handler; + +import com.newrelic.api.agent.weaver.SkipIfPresent; + +@SkipIfPresent +public class StreamHandler { +} diff --git a/instrumentation-security/solr-5.1.0/build.gradle b/instrumentation-security/solr-5.1.0/build.gradle new file mode 100644 index 000000000..8988ab011 --- /dev/null +++ b/instrumentation-security/solr-5.1.0/build.gradle @@ -0,0 +1,32 @@ +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.lucene:lucene-core:4.0.0") + + implementation("org.apache.solr:solr-core:5.1.0") { + transitive = false + } + implementation("org.apache.solr:solr-solrj:5.1.0") { + transitive = false + } + implementation("org.apache.httpcomponents:httpclient:4.3.1") { + transitive = false + } +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.security.instrumentation.solr-5.1.0' } +} + +verifyInstrumentation { + passesOnly 'org.apache.solr:solr-core:[5.1.0,7.0.0)' + + excludeRegex 'org.apache.solr:solr-core:.*(ALPHA|BETA)+$' +} + +site { + title 'Solr' + type 'Datastore' +} \ No newline at end of file diff --git a/instrumentation-security/solr-5.1.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java b/instrumentation-security/solr-5.1.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java new file mode 100644 index 000000000..875a0d378 --- /dev/null +++ b/instrumentation-security/solr-5.1.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java @@ -0,0 +1,111 @@ +/* + * + * * Copyright 2020 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.apache.solr.client.solrj.impl; +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.exceptions.NewRelicSecurityException; +import com.newrelic.api.agent.security.schema.operation.SolrDbOperation; +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 org.apache.http.client.HttpClient; +import org.apache.solr.client.solrj.ResponseParser; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.request.UpdateRequest; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@Weave(type = MatchType.ExactClass, originalName = "org.apache.solr.client.solrj.impl.HttpSolrClient") +public abstract class HttpSolrClient_Instrumentation { + + public abstract String getBaseURL(); + + public HttpSolrClient_Instrumentation(String baseURL, HttpClient client, ResponseParser parser) { + //TODO report external URL + } + + public NamedList request(final SolrRequest request, final ResponseParser processor, String collection) { + boolean isLockAcquired = GenericHelper.acquireLockIfPossible("HTTP_SOLR_REQUEST-", request.hashCode()); + AbstractOperation operation = null; + if(isLockAcquired) { + operation = preprocessSolrRequest(request, "REQUEST"); + } + NamedList result; + try { + result = Weaver.callOriginal(); + } finally { + if(isLockAcquired) { + GenericHelper.releaseLock("HTTP_SOLR_REQUEST-", request.hashCode()); + } + } + registerExitOperation(isLockAcquired, operation); + return result; + } + + private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { + try { + if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() || GenericHelper.skipExistsEvent() + ) { + return; + } + NewRelicSecurity.getAgent().registerExitEvent(operation); + } catch (Throwable e){ + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + } + } + + private AbstractOperation preprocessSolrRequest(SolrRequest request, String methodName) { + try { + String collection = new URL(getBaseURL()).getPath(); + collection = collection.startsWith("/") ? collection.substring(1) : collection; + String method = request.getMethod().toString(); + String path = request.getPath(); + SolrParams solrParams = request.getParams(); + Map params = Collections.emptyMap(); + if(solrParams != null){ + params = SolrParams.toMap(solrParams.toNamedList()); + } + List documents = Collections.emptyList(); + if(request instanceof UpdateRequest) { + documents = ((UpdateRequest) request).getDocuments(); + } + SolrDbOperation solrDbOperation = new SolrDbOperation(this.getClass().getName(), methodName); + solrDbOperation.setCollection(collection); + solrDbOperation.setParams(params); + solrDbOperation.setDocuments(documents); + solrDbOperation.setConnectionURL(getBaseURL()); + solrDbOperation.setMethod(method); + solrDbOperation.setPath(path); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format("Solr request %s, %s, %s, %s, %s", collection, method, path, params, documents), this.getClass().getName()); + NewRelicSecurity.getAgent().registerOperation(solrDbOperation); + return solrDbOperation; + } catch (MalformedURLException e){ + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_5.1.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_5.1.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + } catch (Throwable e) { + if (e instanceof NewRelicSecurityException) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_5.1.0", e.getMessage()), e, this.getClass().getName()); + throw e; + } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_5.1.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_5.1.0", e.getMessage()), e, this.getClass().getName()); + } + return null; + } + +} From c027d22243d168805984c59ea485b4f5f35fe42e Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 23 Jul 2024 21:47:44 +0530 Subject: [PATCH 030/122] Update logging & settings.gradle Co-authored-by: Lovesh Baya --- .../solrj/impl/HttpSolrClient_Instrumentation.java | 10 +++++----- .../solrj/impl/Http2SolrClient_Instrumentation.java | 10 +++++----- .../solrj/impl/HttpSolrClient_Instrumentation.java | 12 ++++++------ .../solrj/impl/Http2SolrClient_Instrumentation.java | 12 ++++++------ .../solrj/impl/HttpSolrClient_Instrumentation.java | 12 ++++++------ settings.gradle | 1 + 6 files changed, 29 insertions(+), 28 deletions(-) diff --git a/instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java b/instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java index bb8bfd0db..350b41f12 100644 --- a/instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java +++ b/instrumentation-security/solr-7.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java @@ -99,15 +99,15 @@ private AbstractOperation preprocessSolrRequest(@SuppressWarnings({"rawtypes"})S NewRelicSecurity.getAgent().registerOperation(solrDbOperation); return solrDbOperation; } catch (MalformedURLException e){ - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_7.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_7.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_7.0.0", e.getMessage()), e, this.getClass().getName()); throw e; } - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_7.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_7.0.0", e.getMessage()), e, this.getClass().getName()); } return null; } diff --git a/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java b/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java index 26177ece3..662098275 100644 --- a/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java +++ b/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java @@ -98,15 +98,15 @@ private AbstractOperation preprocessSolrRequest(@SuppressWarnings({"rawtypes"})S NewRelicSecurity.getAgent().registerOperation(solrDbOperation); return solrDbOperation; } catch (MalformedURLException e){ - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_8.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_8.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_8.0.0", e.getMessage()), e, this.getClass().getName()); throw e; } - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_8.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_8.0.0", e.getMessage()), e, this.getClass().getName()); } return null; } diff --git a/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java b/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java index bb8bfd0db..a02577462 100644 --- a/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java +++ b/instrumentation-security/solr-8.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java @@ -69,7 +69,7 @@ private void registerExitOperation(boolean isProcessingAllowed, AbstractOperatio } NewRelicSecurity.getAgent().registerExitEvent(operation); } catch (Throwable e){ - NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_8.0.0", e.getMessage()), e, this.getClass().getName()); } } @@ -99,15 +99,15 @@ private AbstractOperation preprocessSolrRequest(@SuppressWarnings({"rawtypes"})S NewRelicSecurity.getAgent().registerOperation(solrDbOperation); return solrDbOperation; } catch (MalformedURLException e){ - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_8.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_8.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_8.0.0", e.getMessage()), e, this.getClass().getName()); throw e; } - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_8.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_8.0.0", e.getMessage()), e, this.getClass().getName()); } return null; } diff --git a/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java b/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java index ff9dbca8a..03e576a68 100644 --- a/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java +++ b/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/Http2SolrClient_Instrumentation.java @@ -66,7 +66,7 @@ private void registerExitOperation(boolean isProcessingAllowed, AbstractOperatio } NewRelicSecurity.getAgent().registerExitEvent(operation); } catch (Throwable e){ - NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_9.0.0", e.getMessage()), e, this.getClass().getName()); } } @@ -96,15 +96,15 @@ private AbstractOperation preprocessSolrRequest(@SuppressWarnings({"rawtypes"})S NewRelicSecurity.getAgent().registerOperation(solrDbOperation); return solrDbOperation; } catch (MalformedURLException e){ - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_9.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_9.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_9.0.0", e.getMessage()), e, this.getClass().getName()); throw e; } - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_9.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_9.0.0", e.getMessage()), e, this.getClass().getName()); } return null; } diff --git a/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java b/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java index bb8bfd0db..7806af9b2 100644 --- a/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java +++ b/instrumentation-security/solr-9.0.0/src/main/java/org/apache/solr/client/solrj/impl/HttpSolrClient_Instrumentation.java @@ -69,7 +69,7 @@ private void registerExitOperation(boolean isProcessingAllowed, AbstractOperatio } NewRelicSecurity.getAgent().registerExitEvent(operation); } catch (Throwable e){ - NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_9.0.0", e.getMessage()), e, this.getClass().getName()); } } @@ -99,15 +99,15 @@ private AbstractOperation preprocessSolrRequest(@SuppressWarnings({"rawtypes"})S NewRelicSecurity.getAgent().registerOperation(solrDbOperation); return solrDbOperation; } catch (MalformedURLException e){ - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_4.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_9.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format("Instrumentation library: %s , error while extracting collection from baseUrl : %s, %s", "HTTP_SOLR_SERVER_9.0.0", getBaseURL(), e.getMessage()), e, this.getClass().getName()); } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { - NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_9.0.0", e.getMessage()), e, this.getClass().getName()); throw e; } - NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); - NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_4.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_9.0.0", e.getMessage()), e, this.getClass().getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, "HTTP_SOLR_SERVER_9.0.0", e.getMessage()), e, this.getClass().getName()); } return null; } diff --git a/settings.gradle b/settings.gradle index 6023999fd..bc07ef644 100644 --- a/settings.gradle +++ b/settings.gradle @@ -211,6 +211,7 @@ include 'instrumentation:jedis-3.0.0' include 'instrumentation:jedis-2.7.1_2.7.2' include 'instrumentation:solr-4.0.0' include 'instrumentation:solr-5.0.0' +include 'instrumentation:solr-5.1.0' include 'instrumentation:solr-7.0.0' include 'instrumentation:solr-8.0.0' include 'instrumentation:solr-9.0.0' From e6cd96fd869e4256a8bf9321542e93a46c5dfce9 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 25 Jul 2024 10:51:54 +0530 Subject: [PATCH 031/122] NR-295033: Fix CVE detected in googlecode.json-simple dependency --- newrelic-security-agent/build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/newrelic-security-agent/build.gradle b/newrelic-security-agent/build.gradle index 34c964c35..1935fbb99 100644 --- a/newrelic-security-agent/build.gradle +++ b/newrelic-security-agent/build.gradle @@ -61,7 +61,9 @@ java { dependencies { shadowIntoJar project(":newrelic-security-api") - shadowIntoJar 'com.googlecode.json-simple:json-simple:1.1.1' + shadowIntoJar ('com.googlecode.json-simple:json-simple:1.1.1'){ + exclude(module:'junit', group:'junit') + } shadowIntoJar 'com.fasterxml.jackson.core:jackson-databind:2.14.2' shadowIntoJar 'com.fasterxml.jackson.dataformat:jackson-dataformat-properties:2.14.2' shadowIntoJar 'org.java-websocket:Java-WebSocket:1.5.3' From 372838ae6060c9b2b4ec3012ae2a6eacea68cda2 Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 25 Jul 2024 12:35:51 +0530 Subject: [PATCH 032/122] NR-295033: Remove jackson-dataformat-properties dependency to fix CVE --- newrelic-security-agent/build.gradle | 3 +-- .../java/com/newrelic/api/agent/security/Agent.java | 13 ++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/newrelic-security-agent/build.gradle b/newrelic-security-agent/build.gradle index 1935fbb99..af21ca6ee 100644 --- a/newrelic-security-agent/build.gradle +++ b/newrelic-security-agent/build.gradle @@ -64,8 +64,7 @@ dependencies { shadowIntoJar ('com.googlecode.json-simple:json-simple:1.1.1'){ exclude(module:'junit', group:'junit') } - shadowIntoJar 'com.fasterxml.jackson.core:jackson-databind:2.14.2' - shadowIntoJar 'com.fasterxml.jackson.dataformat:jackson-dataformat-properties:2.14.2' + shadowIntoJar 'com.fasterxml.jackson.core:jackson-databind:2.14.3' shadowIntoJar 'org.java-websocket:Java-WebSocket:1.5.3' shadowIntoJar 'commons-io:commons-io:2.7' shadowIntoJar 'org.apache.commons:commons-text:1.10.0' 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 ab468d430..51c0ef0ca 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 @@ -1,6 +1,6 @@ package com.newrelic.api.agent.security; -import com.fasterxml.jackson.dataformat.javaprop.JavaPropsMapper; +import com.fasterxml.jackson.databind.ObjectMapper; import com.newrelic.agent.security.AgentConfig; import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.dispatcher.DispatcherPool; @@ -29,8 +29,6 @@ import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -43,6 +41,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; @@ -118,7 +117,7 @@ private void initialise() { try { info.setBuildInfo(readCollectorBuildInfo()); - logger.log(LogLevel.INFO, String.format("CSEC Collector build info : %s", new JavaPropsMapper().writeValueAsProperties(info.getBuildInfo())), this.getClass().getName()); + logger.log(LogLevel.INFO, String.format("CSEC Collector build info : %s", new ObjectMapper().writeValueAsString(info.getBuildInfo())), this.getClass().getName()); } catch (IOException e) { // TODO: Need to confirm requirement of this throw. throw new RuntimeException("Unable to read CSEC Collector build info", e); @@ -155,9 +154,9 @@ private void populateApplicationTmpDir() { private BuildInfo readCollectorBuildInfo() { BuildInfo buildInfo = new BuildInfo(); try { - JavaPropsMapper mapper = new JavaPropsMapper(); - buildInfo = mapper. - readValue(CommonUtils.getResourceStreamFromAgentJar("Agent.properties"), BuildInfo.class); + Properties properties = new Properties(); + properties.load(CommonUtils.getResourceStreamFromAgentJar("Agent.properties")); + buildInfo = new ObjectMapper().convertValue(properties, BuildInfo.class); } catch (Throwable e) { logger.log(LogLevel.SEVERE, String.format(CRITICAL_ERROR_UNABLE_TO_READ_BUILD_INFO_AND_VERSION_S_S, e.getMessage(), e.getCause()), this.getClass().getName()); logger.postLogMessageIfNecessary(LogLevel.SEVERE, From 7177ef2c3d1ae4cb5b0ef7697734624710ee1cdb Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 25 Jul 2024 16:25:25 +0530 Subject: [PATCH 033/122] utilise JSONConvertor to log agent build info --- .../security/intcodeagent/properties/BuildInfo.java | 7 +++++++ .../java/com/newrelic/api/agent/security/Agent.java | 10 +++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/properties/BuildInfo.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/properties/BuildInfo.java index ee01b1d59..8c59238c9 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/properties/BuildInfo.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/properties/BuildInfo.java @@ -1,5 +1,7 @@ package com.newrelic.agent.security.intcodeagent.properties; +import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; + import java.time.Clock; public class BuildInfo { @@ -48,4 +50,9 @@ public String getBuildNumber() { public void setBuildNumber(String buildNumber) { this.buildNumber = buildNumber; } + + @Override + public String toString() { + return JsonConverter.toJSON(this); + } } 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 51c0ef0ca..199fbd47a 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 @@ -115,13 +115,9 @@ private void initialise() { String.format("[STEP-2] => Generating unique identifier: %s", AgentInfo.getInstance().getApplicationUUID()), AgentInfo.class.getName()); config.setConfig(CollectorConfigurationUtils.populateCollectorConfig()); - try { - info.setBuildInfo(readCollectorBuildInfo()); - logger.log(LogLevel.INFO, String.format("CSEC Collector build info : %s", new ObjectMapper().writeValueAsString(info.getBuildInfo())), this.getClass().getName()); - } catch (IOException e) { - // TODO: Need to confirm requirement of this throw. - throw new RuntimeException("Unable to read CSEC Collector build info", e); - } + info.setBuildInfo(readCollectorBuildInfo()); + logger.log(LogLevel.INFO, String.format("CSEC Collector build info : %s", info.getBuildInfo()), this.getClass().getName()); + logger.logInit( LogLevel.INFO, "[STEP-3] => Gathering information about the application", From 170ae38956207b7a756c122bb2c4f5d7b13586cb Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 25 Jul 2024 20:43:32 +0530 Subject: [PATCH 034/122] Fix for incorrect line number detected for annotated user class --- .../java/com/newrelic/api/agent/security/Agent.java | 10 +++++++--- 1 file changed, 7 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 ab468d430..ddc9db526 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 @@ -287,9 +287,6 @@ public void registerOperation(AbstractOperation operation) { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); operation.setStackTrace(Arrays.copyOfRange(trace, securityMetaData.getMetaData().getFromJumpRequiredInStackTrace(), trace.length)); } - if(securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod()){ - operation.setUserClassEntity(setUserClassEntityByAnnotation(securityMetaData.getMetaData().getServiceTrace())); - } // added to fetch request/response in case of grpc requests if (securityMetaData.getRequest().getIsGrpc()) { @@ -484,6 +481,13 @@ private UserClassEntity setUserClassEntity(AbstractOperation operation, Security for (int i = operation.getStackTrace().length-1; i >=0 ; i--) { StackTraceElement stackTraceElement = operation.getStackTrace()[i]; + // user class identification using annotations + if (securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod() && StringUtils.equals(stackTraceElement.getClassName(), userStackTraceElement.getClassName()) + && StringUtils.equals(stackTraceElement.getMethodName(), userStackTraceElement.getMethodName())) { + userClassEntity.setUserClassElement(stackTraceElement); + userClassEntity.setCalledByUserCode(securityMetaData.getMetaData().isUserLevelServiceMethodEncountered()); + return userClassEntity; + } // Section for user class identification using API handlers if( !securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod() && URLMappingsHelper.getHandlersHash().contains(stackTraceElement.getClassName().hashCode())){ //Found -> assign user class and return From 9052e8f6a21d558357b41f4d6461b5f9866f4f97 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 26 Jul 2024 22:05:21 +0530 Subject: [PATCH 035/122] Response code interception in akka --- .../src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java | 3 ++- .../main/scala/akka/http/scaladsl/ResponseFutureHelper.scala | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java index 0a0d4fb68..1f32330c9 100644 --- a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java @@ -61,7 +61,7 @@ public static boolean acquireServletLockIfPossible() { return false; } - public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, String className, String methodName, Token token) { + public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, int responseCode, String className, String methodName, Token token) { try { token.linkAndExpire(); if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive()){ @@ -69,6 +69,7 @@ public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringB } NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseContentType(contentType); NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(responseBody); + NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(responseCode); LowSeverityHelper.addRrequestUriToEventFilter(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest()); if(!ServletHelper.isResponseContentTypeExcluded(NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().getResponseContentType())) { diff --git a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala index 1e9b6e179..60a80405f 100644 --- a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala +++ b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/ResponseFutureHelper.scala @@ -41,7 +41,7 @@ object ResponseFutureHelper { processingResult.onComplete { _ => { token.linkAndExpire() - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, response.entity.contentType.toString(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, response.entity.contentType.toString(), response.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) } } @@ -68,7 +68,7 @@ object ResponseFutureHelper { } val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) - AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken()) + AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), httpResponse.status.intValue(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken) } catch { case t: NewRelicSecurityException => NewRelicSecurity.getAgent.log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, AkkaCoreUtils.AKKA_HTTP_CORE_10_0_11, t.getMessage), t, classOf[AkkaCoreUtils].getName) From 385a49eb812ed2685b5af8de2aba25c9a427a846 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 26 Jul 2024 22:06:33 +0530 Subject: [PATCH 036/122] Fix for incorrect line number detected for annotated user class for async processing --- .../java/com/newrelic/api/agent/security/Agent.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 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 ddc9db526..5a4b8c9c2 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 @@ -481,13 +481,6 @@ private UserClassEntity setUserClassEntity(AbstractOperation operation, Security for (int i = operation.getStackTrace().length-1; i >=0 ; i--) { StackTraceElement stackTraceElement = operation.getStackTrace()[i]; - // user class identification using annotations - if (securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod() && StringUtils.equals(stackTraceElement.getClassName(), userStackTraceElement.getClassName()) - && StringUtils.equals(stackTraceElement.getMethodName(), userStackTraceElement.getMethodName())) { - userClassEntity.setUserClassElement(stackTraceElement); - userClassEntity.setCalledByUserCode(securityMetaData.getMetaData().isUserLevelServiceMethodEncountered()); - return userClassEntity; - } // Section for user class identification using API handlers if( !securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod() && URLMappingsHelper.getHandlersHash().contains(stackTraceElement.getClassName().hashCode())){ //Found -> assign user class and return @@ -521,6 +514,12 @@ private UserClassEntity setUserClassEntity(AbstractOperation operation, Security userClassEntity.setCalledByUserCode(securityMetaData.getMetaData().isUserLevelServiceMethodEncountered()); return userClassEntity; } + + // user class identification using annotations + if (userClassEntity.getUserClassElement() == null && securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod()) { + return setUserClassEntityByAnnotation(securityMetaData.getMetaData().getServiceTrace()); + } + if(userClassEntity.getUserClassElement() == null && operation.getStackTrace().length >= 2){ userClassEntity.setUserClassElement(operation.getStackTrace()[1]); userClassEntity.setCalledByUserCode(securityMetaData.getMetaData().isUserLevelServiceMethodEncountered()); From 0e78306b9576ee04ccc89e5897a54a0c94627735 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 29 Jul 2024 16:56:39 +0530 Subject: [PATCH 037/122] Fix for wrong route detection in vertx --- .../java/io/vertx/core/http/HttpServer_Instrumentation.java | 5 +---- .../java/io/vertx/core/http/HttpServer_Instrumentation.java | 6 ++---- .../java/io/vertx/core/http/HttpServer_Instrumentation.java | 5 +---- .../java/io/vertx/core/http/HttpServer_Instrumentation.java | 6 ++---- .../instrumentation/helpers/VertxApiEndpointUtils.java | 3 +++ 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java b/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java index 1624dfcc6..39c730e82 100644 --- a/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java +++ b/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java @@ -8,7 +8,6 @@ import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import io.vertx.core.Handler; -import io.vertx.ext.web.impl.RouterImpl; @Weave(originalName = "io.vertx.core.http.HttpServer", type = MatchType.Interface) public class HttpServer_Instrumentation { @@ -16,9 +15,7 @@ public class HttpServer_Instrumentation { public HttpServer_Instrumentation requestHandler(Handler handler){ HttpServer_Instrumentation server = Weaver.callOriginal(); try { - if (handler instanceof RouterImpl) { - VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); - } + VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, "VERTX-CORE-3.3.0", e.getMessage()), e, VertxApiEndpointUtils.class.getName()); } diff --git a/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java b/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java index bdea6e2c1..b7fbb5b67 100644 --- a/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java +++ b/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java @@ -8,7 +8,7 @@ import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import io.vertx.core.Handler; -import io.vertx.ext.web.impl.RouterImpl; + @Weave(originalName = "io.vertx.core.http.HttpServer", type = MatchType.Interface) public class HttpServer_Instrumentation { @@ -16,9 +16,7 @@ public class HttpServer_Instrumentation { public HttpServer_Instrumentation requestHandler(Handler handler){ HttpServer_Instrumentation server = Weaver.callOriginal(); try { - if (handler instanceof RouterImpl) { - VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); - } + VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, "VERTX-CORE-3.4.0", e.getMessage()), e, VertxApiEndpointUtils.class.getName()); } diff --git a/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java b/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java index 5dbf5d6a9..52435cc6f 100644 --- a/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java +++ b/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java @@ -7,7 +7,6 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import io.vertx.ext.web.impl.RouterImpl; import io.vertx.core.Handler; @Weave(originalName = "io.vertx.core.http.HttpServer", type = MatchType.Interface) @@ -16,9 +15,7 @@ public class HttpServer_Instrumentation { public HttpServer_Instrumentation requestHandler(Handler handler){ HttpServer_Instrumentation server = Weaver.callOriginal(); try { - if (handler instanceof RouterImpl) { - VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); - } + VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, "VERTX-CORE-3.7.1", e.getMessage()), e, VertxApiEndpointUtils.class.getName()); } diff --git a/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java b/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java index 096589c04..d030b540a 100644 --- a/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java +++ b/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/HttpServer_Instrumentation.java @@ -8,7 +8,7 @@ import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import io.vertx.core.Handler; -import io.vertx.ext.web.impl.RouterImpl; + @Weave(originalName = "io.vertx.core.http.HttpServer", type = MatchType.Interface) @@ -17,9 +17,7 @@ public class HttpServer_Instrumentation { public HttpServer_Instrumentation requestHandler(Handler handler){ HttpServer_Instrumentation server = Weaver.callOriginal(); try { - if (handler instanceof RouterImpl) { - VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); - } + VertxApiEndpointUtils.getInstance().generateAPIEndpoints(handler.hashCode()); } catch (Exception e){ NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, "VERTX-CORE-4.0.0", e.getMessage()), e, VertxApiEndpointUtils.class.getName()); } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java index 7dbf60ca1..1f7c990ac 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java @@ -155,6 +155,9 @@ public String getPath(String path, Object pattern) { public void routeDetection(String path, Pattern pattern) { if (NewRelicSecurity.isHookProcessingActive()){ + if (URLMappingsHelper.getSegmentCount(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().getRoute()) == URLMappingsHelper.getSegmentCount(path)) { + return; + } boolean isAlreadyServlet = Objects.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().getFramework(), Framework.SERVLET.name()); if (path != null){ NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(path, isAlreadyServlet); From 04249a6f97b6bdf31108b867ae99723bdb76f0c4 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 29 Jul 2024 18:28:36 +0530 Subject: [PATCH 038/122] API Endpoint detection if handler is not object of Router in vertx --- .../web/impl/RouteImpl_Instrumentation.java | 1 + .../web/impl/RouteImpl_Instrumentation.java | 1 + .../web/impl/RouteState_Instrumentation.java | 3 ++ .../helpers/VertxApiEndpointUtils.java | 29 ++++++++++++------- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java b/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java index 0a160d421..7135ea14d 100644 --- a/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java +++ b/instrumentation-security/vertx-web-3.2.0/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java @@ -45,6 +45,7 @@ public abstract class RouteImpl_Instrumentation { synchronized void handleContext(RoutingContext context) { try { + VertxApiEndpointUtils.getInstance().generateAPIEndpointsIfNotPresent(this.hashCode()); VertxApiEndpointUtils.getInstance().routeDetection(path, pattern); } catch (Exception e) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, "VERTX-WEB-3.2.0", e.getMessage()), e, this.getClass().getName()); diff --git a/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java b/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java index 6a28d9f35..683a6cfdb 100644 --- a/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java +++ b/instrumentation-security/vertx-web-3.5.1/src/main/java/io/vertx/ext/web/impl/RouteImpl_Instrumentation.java @@ -46,6 +46,7 @@ public class RouteImpl_Instrumentation { void handleContext(RoutingContextImplBase context) { try { + VertxApiEndpointUtils.getInstance().generateAPIEndpointsIfNotPresent(this.hashCode()); VertxApiEndpointUtils.getInstance().routeDetection(path, pattern); } catch (Exception e) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, "VERTX-WEB-3.5.1", e.getMessage()), e, this.getClass().getName()); diff --git a/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteState_Instrumentation.java b/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteState_Instrumentation.java index 6c451c238..92a1fae66 100644 --- a/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteState_Instrumentation.java +++ b/instrumentation-security/vertx-web-3.8.3/src/main/java/io/vertx/ext/web/impl/RouteState_Instrumentation.java @@ -13,8 +13,11 @@ @Weave(originalName = "io.vertx.ext.web.impl.RouteState") abstract class RouteState_Instrumentation { + private final RouteImpl route = Weaver.callOriginal(); + void handleContext(RoutingContextImplBase context){ try { + VertxApiEndpointUtils.getInstance().generateAPIEndpointsIfNotPresent(route.hashCode()); VertxApiEndpointUtils.getInstance().routeDetection(getPath(), getPattern()); } catch (Exception e) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, "VERTX-WEB-3.8.3", e.getMessage()), e, this.getClass().getName()); diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java index 1f7c990ac..47de7398a 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/VertxApiEndpointUtils.java @@ -39,7 +39,7 @@ private void addRouteImpl(int routerHashCode, int routeHashCode) throws Exceptio if (!routes.containsKey(routerHashCode)) { routes.put(routerHashCode, new ConcurrentHashMap<>()); } - routes.get(routerHashCode).put(route.hashCode(), route); + routes.get(routerHashCode).put(routeHashCode, route); } } finally { if (isLockAcquired) { @@ -54,7 +54,7 @@ public void addRouteImpl(int routerHashCode, int routeHashCode, String path, Str if (!routes.containsKey(routerHashCode)){ return; } - VertxRoute route = routes.get(routerHashCode).get(Objects.hash(routerHashCode, routeHashCode)); + VertxRoute route = routes.get(routerHashCode).get(routeHashCode); if (route == null){ return; } @@ -77,7 +77,7 @@ public void addHandlerClass(int routerHashCode, int routeHashCode, String handle if (!routes.containsKey(routerHashCode)){ return; } - VertxRoute route = routes.get(routerHashCode).get(Objects.hash(routerHashCode, routeHashCode)); + VertxRoute route = routes.get(routerHashCode).get(routeHashCode); if (route == null || !Objects.isNull(route.getHandlerName())){ return; } @@ -99,7 +99,7 @@ public void resolveSubRoutes(int parentRouterHashCode, int childRouterHashCode, String subRoutePath = getPath(route.getPath(), route.getPattern()); route.setPath(StringUtils.removeEnd(path, StringUtils.SEPARATOR) + StringUtils.prependIfMissing(subRoutePath, StringUtils.SEPARATOR)); route.setRouterHashCode(parentRouterHashCode); - routes.get(parentRouterHashCode).put(route.hashCode(), route); + routes.get(parentRouterHashCode).put(route.getRouteHashCode(), route); } } catch (Exception e) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_APP_ENDPOINTS, VERTX_FRAMEWORK, e.getMessage()), e, VertxApiEndpointUtils.class.getName()); @@ -155,16 +155,25 @@ public String getPath(String path, Object pattern) { public void routeDetection(String path, Pattern pattern) { if (NewRelicSecurity.isHookProcessingActive()){ - if (URLMappingsHelper.getSegmentCount(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().getRoute()) == URLMappingsHelper.getSegmentCount(path)) { - return; - } - boolean isAlreadyServlet = Objects.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().getFramework(), Framework.SERVLET.name()); + String route = StringUtils.EMPTY; if (path != null){ - NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(path, isAlreadyServlet); + route = path; } else if (pattern != null){ - NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(pattern.pattern(), isAlreadyServlet); + route = pattern.pattern(); + } + if (URLMappingsHelper.getSegmentCount(NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().getRoute()) == URLMappingsHelper.getSegmentCount(route)) { + return; } + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(route, Objects.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().getFramework(), Framework.SERVLET.name())); NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.VERTX); } } + + public void generateAPIEndpointsIfNotPresent(int routeHashCode) { + for (Map.Entry> routesSet : routes.entrySet()) { + if (routesSet.getValue().containsKey(routeHashCode)) { + generateAPIEndpoints(routesSet.getKey()); + } + } + } } From 181c987443c822c33bea2beecdc8429ce31f438f Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 29 Jul 2024 18:41:22 +0530 Subject: [PATCH 039/122] Use ThreadLocalLockHelper to ensure only application behaviour is captured --- .../newrelic/api/agent/security/Agent.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 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 da910b3dd..235ef750c 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 @@ -841,13 +841,21 @@ 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; + boolean lockAcquired = ThreadLocalLockHelper.acquireLock(); + try { + if (lockAcquired) { + 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; + } + } + } finally { + ThreadLocalLockHelper.releaseLock(); } + return null; } @Override From 7c44820f06ac03c0f0f2293276276477b8b81d55 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 2 Aug 2024 09:51:34 +0530 Subject: [PATCH 040/122] Fix for CVEs --- gradle/script/java.gradle | 2 +- instrumentation-security-test/build.gradle | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/gradle/script/java.gradle b/gradle/script/java.gradle index 38c9b374d..f7c6663cf 100644 --- a/gradle/script/java.gradle +++ b/gradle/script/java.gradle @@ -264,7 +264,7 @@ test { } dependencies { - testImplementation("junit:junit:4.12") + testImplementation("junit:junit:4.13.2") testImplementation("org.mockito:mockito-core:3.9.0") testImplementation("org.hamcrest:hamcrest-library:1.3") testImplementation(project(":test-annotations")) diff --git a/instrumentation-security-test/build.gradle b/instrumentation-security-test/build.gradle index 917a6071c..835fb8f6e 100644 --- a/instrumentation-security-test/build.gradle +++ b/instrumentation-security-test/build.gradle @@ -14,13 +14,15 @@ dependencies { implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") implementation("com.newrelic.agent.java:newrelic-agent:${nrAgentVersion}") - implementation 'org.apache.commons:commons-text:1.7' + implementation ('org.apache.commons:commons-text:1.10.0') implementation("com.newrelic.agent.java:agent-bridge:${nrAPIVersion}") implementation("com.newrelic.agent.java:agent-bridge-datastore:${nrAPIVersion}") implementation("commons-net:commons-net:3.9.0") implementation("org.mockftpserver:MockFtpServer:3.1.0") - api("org.apache.httpcomponents:httpclient:4.5.13") + api("org.apache.httpcomponents:httpclient:4.5.13"){ + exclude(module: 'commons-codec', group: 'commons-codec') + } api("org.nanohttpd:nanohttpd:2.3.1") } From af4a26a1b59a4c1ce58ba760d412191256af770a Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 2 Aug 2024 11:29:35 +0530 Subject: [PATCH 041/122] Initial draft for IAST in restricted mode --- .../newrelic/agent/security/AgentConfig.java | 113 +- .../utils/InstrumentationUtils.java | 8 +- .../ControlCommandProcessor.java | 5 +- .../models/collectorconfig/AgentMode.java | 55 + .../schedulers/SchedulerHelper.java | 6 +- .../intcodeagent/utils/CronExpression.java | 1428 +++++++++++++++++ .../utils/RestrictionUtility.java | 340 ++++ .../intcodeagent/websocket/EventSendPool.java | 2 +- .../intcodeagent/websocket/WSClient.java | 10 +- .../agent/security/util/IUtilConstants.java | 15 + .../newrelic/api/agent/security/Agent.java | 52 +- .../agent/security/schema/HttpRequest.java | 62 + .../schema/annotations/JsonProperty.java | 14 + .../security/schema/policy/AccountInfo.java | 18 + .../schema/policy/HttpParameterLocation.java | 9 + .../security/schema/policy/IASTScan.java | 19 +- .../schema/policy/MappingParameters.java | 40 + .../security/schema/policy/RASPScan.java | 17 + .../schema/policy/RestrictionCriteria.java | 60 + .../security/schema/policy/ScanTime.java | 39 + .../schema/policy/SkipScanParameters.java | 52 + .../schema/policy/StrictMappings.java | 46 + .../schema/policy/VulnerabilityScan.java | 2 +- 23 files changed, 2384 insertions(+), 28 deletions(-) create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/collectorconfig/AgentMode.java create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/CronExpression.java create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/annotations/JsonProperty.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/AccountInfo.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/HttpParameterLocation.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameters.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RASPScan.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanTime.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScanParameters.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/StrictMappings.java 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 af043606f..2fdec7789 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 @@ -1,16 +1,24 @@ package com.newrelic.agent.security; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.Annotated; +import com.fasterxml.jackson.databind.introspect.AnnotatedMember; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.newrelic.agent.security.instrumentator.os.OSVariables; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.instrumentator.utils.AgentUtils; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; +import com.newrelic.agent.security.intcodeagent.models.collectorconfig.AgentMode; +import com.newrelic.agent.security.intcodeagent.utils.CronExpression; +import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; +import com.newrelic.api.agent.security.schema.annotations.JsonProperty; +import com.newrelic.api.agent.security.schema.policy.*; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.filelogging.LogWriter; import com.newrelic.agent.security.intcodeagent.models.collectorconfig.CollectorConfig; import com.newrelic.agent.security.intcodeagent.utils.CommonUtils; import com.newrelic.agent.security.util.IUtilConstants; import com.newrelic.api.agent.NewRelic; -import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import org.apache.commons.io.FileUtils; import org.apache.commons.io.comparator.LastModifiedFileComparator; import org.apache.commons.io.filefilter.FileFilterUtils; @@ -21,10 +29,11 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collection; +import java.text.ParseException; +import java.time.Instant; +import java.util.*; -import static com.newrelic.agent.security.util.IUtilConstants.DIRECTORY_PERMISSION; +import static com.newrelic.agent.security.util.IUtilConstants.*; public class AgentConfig { @@ -38,6 +47,8 @@ public class AgentConfig { private String groupName; + private AgentMode agentMode; + private CollectorConfig config = new CollectorConfig(); private boolean isNRSecurityEnabled; @@ -49,7 +60,7 @@ public class AgentConfig { private AgentConfig(){ } - public void instantiate(){ + public long instantiate(){ //Set k2 home path try { boolean validHomePath = setK2HomePath(); @@ -68,6 +79,90 @@ public void instantiate(){ //Instantiation call please do not move or repeat this. osVariables = OsVariablesInstance.instantiate().getOsVariables(); + + instantiateAgentMode(groupName); + + return trigerIAST(); + } + + public long trigerIAST() { + if(agentMode.getIastScan().getEnabled() && agentMode.getIastScan().getRestricted()){ + long date = agentMode.getIastScan().getRestrictionCriteria().getScanTime().getNextScanTime().getTime(); + long currentTime = Instant.now().toEpochMilli(); + System.out.println("IAST is in restricted mode will start at "+date); + return date-currentTime; + } + return 0; + } + + private void instantiateAgentMode(String groupName) { + this.agentMode = new AgentMode(groupName); + switch (groupName){ + case IAST: + //this is default case which requires no changes + break; + case RASP: + readRaspConfig(); + break; + case IAST_RESTRICTED: + readIastRestrictedConfig(); + break; + default: + //this is default case which requires no changes + break; + } + + } + + private void readIastRestrictedConfig() { + this.agentMode.getIastScan().setRestricted(true); + RestrictionCriteria restrictionCriteria = this.agentMode.getIastScan().getRestrictionCriteria(); + restrictionCriteria.setAccountInfo(new AccountInfo(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID))); + if(StringUtils.isBlank(restrictionCriteria.getAccountInfo().getAccountId())) { + //TODO raise error + + } + + restrictionCriteria.getScanTime().setDuration(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SCAN_TIME_DURATION, 5)); + restrictionCriteria.getScanTime().setSchedule(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SCAN_TIME_SCHEDULE, "0 0 2 * * MON")); + if(CronExpression.isValidExpression(restrictionCriteria.getScanTime().getSchedule())){ + try { + restrictionCriteria.getScanTime().setNextScanTime(new CronExpression(restrictionCriteria.getScanTime().getSchedule()).getTimeAfter(new Date())); + } catch (ParseException e) { + //TODO log error and set default scan time + } + } else { + //TODO raise error + } + + //Mapping parameters + List> mappingParameters = NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS, Collections.emptyList()); + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() { + + }); + for (Map mappingParameter : mappingParameters) { + MappingParameters matchingCriteria = new MappingParameters(HttpParameterLocation.valueOf(mappingParameter.get("account_id_location")), mappingParameter.get("account_id_key")); +// MappingParameters matchingCriteria = mapper.convertValue(mappingParameter, MappingParameters.class); + restrictionCriteria.getMappingParameters().add(matchingCriteria); + } + //Skip Scan Parameters + restrictionCriteria.getSkipScanParameters().setBody(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_BODY, Collections.emptyList())); + restrictionCriteria.getSkipScanParameters().setHeader(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_HEADER, Collections.emptyList())); + restrictionCriteria.getSkipScanParameters().setQuery(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_QUERY, Collections.emptyList())); + + //Strict Criteria + List> strictCriteria = NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_STRICT, Collections.emptyList()); + for (Map strictCriterion : strictCriteria) { + StrictMappings matchingCriteria = mapper.convertValue(strictCriterion, StrictMappings.class); + restrictionCriteria.getStrictMappings().add(matchingCriteria); + } + + } + + private void readRaspConfig() { + this.agentMode.getIastScan().setEnabled(false); + this.agentMode.getRaspScan().setEnabled(true); } private static final class InstanceHolder { @@ -164,6 +259,10 @@ public void setConfig(CollectorConfig config) { this.config = config; } + public String getLogLevel() { + return logLevel; + } + public void createSnapshotDirectory() throws IOException { Path snapshotDir = Paths.get(osVariables.getSnapshotDir()); // Remove any file with this name from target. @@ -207,4 +306,8 @@ public void setNRSecurityEnabled(boolean NRSecurityEnabled) { public String getK2Home() { return NR_CSEC_HOME; } + + public AgentMode getAgentMode() { + return agentMode; + } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/InstrumentationUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/InstrumentationUtils.java index 0cf9bb752..c97777b98 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/InstrumentationUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/InstrumentationUtils.java @@ -5,6 +5,7 @@ import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessorThreadPool; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; +import com.newrelic.agent.security.intcodeagent.schedulers.FileCleaner; 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; @@ -13,6 +14,7 @@ import com.newrelic.agent.security.intcodeagent.websocket.WSClient; import com.newrelic.agent.security.intcodeagent.websocket.WSReconnectionST; import org.apache.commons.io.FileUtils; +import org.java_websocket.framing.CloseFrame; import java.io.File; import java.util.concurrent.TimeUnit; @@ -47,7 +49,7 @@ public class InstrumentationUtils { private static Boolean IAST = false; - public static void shutdownLogic(boolean doResetInstrumentation) { + public static void shutdownLogic() { // System.out.println("K2 Collector's shutdown hooked called."); // AgentUtils.getInstance().setAgentActive(false); try { @@ -67,13 +69,13 @@ public static void shutdownLogic(boolean doResetInstrumentation) { } catch (Throwable e) { } try { -// ServletEventPool.getInstance().shutDownThreadPoolExecutor(); HealthCheckScheduleThread.getInstance().cancelTask(true); -// EventThreadPool.getInstance().shutDownThreadPoolExecutor(); DispatcherPool.shutDownPool(); ControlCommandProcessorThreadPool.shutDownPool(); EventSendPool.shutDownPool(); WSReconnectionST.shutDownPool(); + WSClient.shutDownWSClient(true, CloseFrame.NORMAL, "IAST agent shutting down"); + FileCleaner.cancelTask(); FileUtils.deleteQuietly(new File(OsVariablesInstance.getInstance().getOsVariables().getTmpDirectory())); } catch (Throwable e) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java index f66a634d4..3113cf3d5 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java @@ -12,7 +12,6 @@ import com.newrelic.agent.security.intcodeagent.models.config.AgentPolicyParameters; import com.newrelic.agent.security.intcodeagent.models.javaagent.EventResponse; import com.newrelic.agent.security.intcodeagent.models.javaagent.IntCodeControlCommand; -import com.newrelic.agent.security.intcodeagent.utils.CommonUtils; import com.newrelic.agent.security.intcodeagent.websocket.EventSendPool; import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; import com.newrelic.agent.security.intcodeagent.websocket.WSClient; @@ -107,13 +106,13 @@ public void run() { switch (controlCommand.getControlCommand()) { case IntCodeControlCommand.SHUTDOWN_LANGUAGE_AGENT: - InstrumentationUtils.shutdownLogic(true); + InstrumentationUtils.shutdownLogic(); break; case IntCodeControlCommand.UNSUPPORTED_AGENT: logger.log(LogLevel.SEVERE, controlCommand.getArguments().get(0), ControlCommandProcessor.class.getSimpleName()); System.err.println(controlCommand.getArguments().get(0)); - InstrumentationUtils.shutdownLogic(true); + InstrumentationUtils.shutdownLogic(); break; case IntCodeControlCommand.SEND_POLICY_PARAMETERS: diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/collectorconfig/AgentMode.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/collectorconfig/AgentMode.java new file mode 100644 index 000000000..6f24cc64f --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/collectorconfig/AgentMode.java @@ -0,0 +1,55 @@ +package com.newrelic.agent.security.intcodeagent.models.collectorconfig; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; +import com.newrelic.api.agent.security.schema.policy.IASTScan; +import com.newrelic.api.agent.security.schema.policy.RASPScan; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder(alphabetic = true) +public class AgentMode { + + private String mode; + + private IASTScan iastScan; + + private RASPScan raspScan; + + public AgentMode() {} + + public AgentMode(String mode) { + this.mode = mode; + iastScan = new IASTScan(); + raspScan = new RASPScan(); + } + + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } + + public IASTScan getIastScan() { + return iastScan; + } + + public void setIastScan(IASTScan iastScan) { + this.iastScan = iastScan; + } + + public RASPScan getRaspScan() { + return raspScan; + } + + public void setRaspScan(RASPScan raspScan) { + this.raspScan = raspScan; + } + + @Override + public String toString() { + return JsonConverter.toJSON(this); + } +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java index a68025e68..8568a08a1 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java @@ -1,6 +1,5 @@ package com.newrelic.agent.security.intcodeagent.schedulers; -import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.filelogging.LogFileHelper; import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; import com.newrelic.agent.security.util.IUtilConstants; @@ -11,7 +10,6 @@ import java.util.concurrent.atomic.AtomicInteger; public class SchedulerHelper { - private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); private final ScheduledExecutorService commonExecutor; @@ -39,6 +37,10 @@ public static SchedulerHelper getInstance() { private final Map> scheduledFutureMap = new ConcurrentHashMap<>(); + public ScheduledFuture scheduleIastTrigger(Runnable runnable, long initialDelay, TimeUnit unit) { + return commonExecutor.schedule(runnable, initialDelay, unit); + } + public ScheduledFuture scheduleHealthCheck(Runnable command, long initialDelay, long period, diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/CronExpression.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/CronExpression.java new file mode 100644 index 000000000..07d44d370 --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/CronExpression.java @@ -0,0 +1,1428 @@ +package com.newrelic.agent.security.intcodeagent.utils; + +import java.text.ParseException; +import java.util.*; + +public class CronExpression { + + protected static final int SECOND = 0; + protected static final int MINUTE = 1; + protected static final int HOUR = 2; + protected static final int DAY_OF_MONTH = 3; + protected static final int MONTH = 4; + protected static final int DAY_OF_WEEK = 5; + protected static final int YEAR = 6; + protected static final int ALL_SPEC_INT = 99; // '*' + protected static final int NO_SPEC_INT = 98; // '?' + protected static final Integer ALL_SPEC = ALL_SPEC_INT; + protected static final Integer NO_SPEC = NO_SPEC_INT; + + protected static final Map monthMap = new HashMap(20); + protected static final Map dayMap = new HashMap(60); + static { + monthMap.put("JAN", 0); + monthMap.put("FEB", 1); + monthMap.put("MAR", 2); + monthMap.put("APR", 3); + monthMap.put("MAY", 4); + monthMap.put("JUN", 5); + monthMap.put("JUL", 6); + monthMap.put("AUG", 7); + monthMap.put("SEP", 8); + monthMap.put("OCT", 9); + monthMap.put("NOV", 10); + monthMap.put("DEC", 11); + + dayMap.put("SUN", 1); + dayMap.put("MON", 2); + dayMap.put("TUE", 3); + dayMap.put("WED", 4); + dayMap.put("THU", 5); + dayMap.put("FRI", 6); + dayMap.put("SAT", 7); + } + + private final String cronExpression; + private TimeZone timeZone = null; + protected transient TreeSet seconds; + protected transient TreeSet minutes; + protected transient TreeSet hours; + protected transient TreeSet daysOfMonth; + protected transient TreeSet months; + protected transient TreeSet daysOfWeek; + protected transient TreeSet years; + + protected transient boolean lastdayOfWeek = false; + protected transient int nthdayOfWeek = 0; + protected transient boolean lastdayOfMonth = false; + protected transient boolean nearestWeekday = false; + protected transient int lastdayOffset = 0; + protected transient boolean expressionParsed = false; + + public static final int MAX_YEAR = Calendar.getInstance().get(Calendar.YEAR) + 100; + + public CronExpression(String cronExpression) throws ParseException { + this.cronExpression = cronExpression.toUpperCase(Locale.US); + + buildExpression(this.cronExpression); + } + + /** + * Indicates whether the given date satisfies the cron expression. Note that + * milliseconds are ignored, so two Dates falling on different milliseconds + * of the same second will always have the same result here. + * + * @param date the date to evaluate + * @return a boolean indicating whether the given date satisfies the cron + * expression + */ + public boolean isSatisfiedBy(Date date) { + Calendar testDateCal = Calendar.getInstance(getTimeZone()); + testDateCal.setTime(date); + testDateCal.set(Calendar.MILLISECOND, 0); + Date originalDate = testDateCal.getTime(); + + testDateCal.add(Calendar.SECOND, -1); + + Date timeAfter = getTimeAfter(testDateCal.getTime()); + + return ((timeAfter != null) && (timeAfter.equals(originalDate))); + } + + /** + * Returns the next date/time after the given date/time which + * satisfies the cron expression. + * + * @param date the date/time at which to begin the search for the next valid + * date/time + * @return the next valid date/time + */ + public Date getNextValidTimeAfter(Date date) { + return getTimeAfter(date); + } + + /** + * Returns the next date/time after the given date/time which does + * not satisfy the expression + * + * @param date the date/time at which to begin the search for the next + * invalid date/time + * @return the next valid date/time + */ + public Date getNextInvalidTimeAfter(Date date) { + long difference = 1000; + + //move back to the nearest second so differences will be accurate + Calendar adjustCal = Calendar.getInstance(getTimeZone()); + adjustCal.setTime(date); + adjustCal.set(Calendar.MILLISECOND, 0); + Date lastDate = adjustCal.getTime(); + + Date newDate; + + //FUTURE_TODO: (QUARTZ-481) IMPROVE THIS! The following is a BAD solution to this problem. Performance will be very bad here, depending on the cron expression. It is, however A solution. + + //keep getting the next included time until it's farther than one second + // apart. At that point, lastDate is the last valid fire time. We return + // the second immediately following it. + while (difference == 1000) { + newDate = getTimeAfter(lastDate); + if(newDate == null) + break; + + difference = newDate.getTime() - lastDate.getTime(); + + if (difference == 1000) { + lastDate = newDate; + } + } + + return new Date(lastDate.getTime() + 1000); + } + + /** + * Returns the time zone for which this CronExpression + * will be resolved. + */ + public TimeZone getTimeZone() { + if (timeZone == null) { + timeZone = TimeZone.getDefault(); + } + + return timeZone; + } + + /** + * Sets the time zone for which this CronExpression + * will be resolved. + */ + public void setTimeZone(TimeZone timeZone) { + this.timeZone = timeZone; + } + + /** + * Returns the string representation of the CronExpression + * + * @return a string representation of the CronExpression + */ + @Override + public String toString() { + return cronExpression; + } + + /** + * Indicates whether the specified cron expression can be parsed into a + * valid cron expression + * + * @param cronExpression the expression to evaluate + * @return a boolean indicating whether the given expression is a valid cron + * expression + */ + public static boolean isValidExpression(String cronExpression) { + + try { + new CronExpression(cronExpression); + } catch (ParseException pe) { + return false; + } + + return true; + } + + public static void validateExpression(String cronExpression) throws ParseException { + + new CronExpression(cronExpression); + } + + + //////////////////////////////////////////////////////////////////////////// + // + // Expression Parsing Functions + // + //////////////////////////////////////////////////////////////////////////// + + protected void buildExpression(String expression) throws ParseException { + expressionParsed = true; + + try { + + if (seconds == null) { + seconds = new TreeSet(); + } + if (minutes == null) { + minutes = new TreeSet(); + } + if (hours == null) { + hours = new TreeSet(); + } + if (daysOfMonth == null) { + daysOfMonth = new TreeSet(); + } + if (months == null) { + months = new TreeSet(); + } + if (daysOfWeek == null) { + daysOfWeek = new TreeSet(); + } + if (years == null) { + years = new TreeSet(); + } + + int exprOn = SECOND; + + StringTokenizer exprsTok = new StringTokenizer(expression, " \t", + false); + + while (exprsTok.hasMoreTokens() && exprOn <= YEAR) { + String expr = exprsTok.nextToken().trim(); + + // throw an exception if L is used with other days of the month + if(exprOn == DAY_OF_MONTH && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' and 'LW' with other days of the month is not implemented", -1); + } + // throw an exception if L is used with other days of the week + if(exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' with other days of the week is not implemented", -1); + } + if(exprOn == DAY_OF_WEEK && expr.indexOf('#') != -1 && expr.indexOf('#', expr.indexOf('#') +1) != -1) { + throw new ParseException("Support for specifying multiple \"nth\" days is not implemented.", -1); + } + + StringTokenizer vTok = new StringTokenizer(expr, ","); + while (vTok.hasMoreTokens()) { + String v = vTok.nextToken(); + storeExpressionVals(0, v, exprOn); + } + + exprOn++; + } + + if (exprOn <= DAY_OF_WEEK) { + throw new ParseException("Unexpected end of expression.", + expression.length()); + } + + if (exprOn <= YEAR) { + storeExpressionVals(0, "*", YEAR); + } + + TreeSet dow = getSet(DAY_OF_WEEK); + TreeSet dom = getSet(DAY_OF_MONTH); + + // Copying the logic from the UnsupportedOperationException below + boolean dayOfMSpec = !dom.contains(NO_SPEC); + boolean dayOfWSpec = !dow.contains(NO_SPEC); + + if (!dayOfMSpec || dayOfWSpec) { + if (!dayOfWSpec || dayOfMSpec) { + throw new ParseException( + "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.", 0); + } + } + } catch (ParseException pe) { + throw pe; + } catch (Exception e) { + throw new ParseException("Illegal cron expression format (" + + e.toString() + ")", 0); + } + } + + protected int storeExpressionVals(int pos, String s, int type) + throws ParseException { + + int incr = 0; + int i = skipWhiteSpace(pos, s); + if (i >= s.length()) { + return i; + } + char c = s.charAt(i); + if ((c >= 'A') && (c <= 'Z') && (!s.equals("L")) && (!s.equals("LW")) && (!s.matches("^L-[0-9]*[W]?"))) { + String sub = s.substring(i, i + 3); + int sval = -1; + int eval = -1; + if (type == MONTH) { + sval = getMonthNumber(sub) + 1; + if (sval <= 0) { + throw new ParseException("Invalid Month value: '" + sub + "'", i); + } + if (s.length() > i + 3) { + c = s.charAt(i + 3); + if (c == '-') { + i += 4; + sub = s.substring(i, i + 3); + eval = getMonthNumber(sub) + 1; + if (eval <= 0) { + throw new ParseException("Invalid Month value: '" + sub + "'", i); + } + } + } + } else if (type == DAY_OF_WEEK) { + sval = getDayOfWeekNumber(sub); + if (sval < 0) { + throw new ParseException("Invalid Day-of-Week value: '" + + sub + "'", i); + } + if (s.length() > i + 3) { + c = s.charAt(i + 3); + if (c == '-') { + i += 4; + sub = s.substring(i, i + 3); + eval = getDayOfWeekNumber(sub); + if (eval < 0) { + throw new ParseException( + "Invalid Day-of-Week value: '" + sub + + "'", i); + } + } else if (c == '#') { + try { + i += 4; + nthdayOfWeek = Integer.parseInt(s.substring(i)); + if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + throw new Exception(); + } + } catch (Exception e) { + throw new ParseException( + "A numeric value between 1 and 5 must follow the '#' option", + i); + } + } else if (c == 'L') { + lastdayOfWeek = true; + i++; + } + } + + } else { + throw new ParseException( + "Illegal characters for this position: '" + sub + "'", + i); + } + if (eval != -1) { + incr = 1; + } + addToSet(sval, eval, incr, type); + return (i + 3); + } + + if (c == '?') { + i++; + if ((i + 1) < s.length() + && (s.charAt(i) != ' ' && s.charAt(i + 1) != '\t')) { + throw new ParseException("Illegal character after '?': " + + s.charAt(i), i); + } + if (type != DAY_OF_WEEK && type != DAY_OF_MONTH) { + throw new ParseException( + "'?' can only be specified for Day-of-Month or Day-of-Week.", + i); + } + if (type == DAY_OF_WEEK && !lastdayOfMonth) { + int val = daysOfMonth.last(); + if (val == NO_SPEC_INT) { + throw new ParseException( + "'?' can only be specified for Day-of-Month -OR- Day-of-Week.", + i); + } + } + + addToSet(NO_SPEC_INT, -1, 0, type); + return i; + } + + if (c == '*' || c == '/') { + if (c == '*' && (i + 1) >= s.length()) { + addToSet(ALL_SPEC_INT, -1, incr, type); + return i + 1; + } else if (c == '/' + && ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s + .charAt(i + 1) == '\t')) { + throw new ParseException("'/' must be followed by an integer.", i); + } else if (c == '*') { + i++; + } + c = s.charAt(i); + if (c == '/') { // is an increment specified? + i++; + if (i >= s.length()) { + throw new ParseException("Unexpected end of string.", i); + } + + incr = getNumericValue(s, i); + + i++; + if (incr > 10) { + i++; + } + checkIncrementRange(incr, type, i); + } else { + incr = 1; + } + + addToSet(ALL_SPEC_INT, -1, incr, type); + return i; + } else if (c == 'L') { + i++; + if (type == DAY_OF_MONTH) { + lastdayOfMonth = true; + } + if (type == DAY_OF_WEEK) { + addToSet(7, 7, 0, type); + } + if(type == DAY_OF_MONTH && s.length() > i) { + c = s.charAt(i); + if(c == '-') { + ValueSet vs = getValue(0, s, i+1); + lastdayOffset = vs.value; + if(lastdayOffset > 30) + throw new ParseException("Offset from last day must be <= 30", i+1); + i = vs.pos; + } + if(s.length() > i) { + c = s.charAt(i); + if(c == 'W') { + nearestWeekday = true; + i++; + } + } + } + return i; + } else if (c >= '0' && c <= '9') { + int val = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + addToSet(val, -1, -1, type); + } else { + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(val, s, i); + val = vs.value; + i = vs.pos; + } + i = checkNext(i, s, val, type); + return i; + } + } else { + throw new ParseException("Unexpected character: " + c, i); + } + + return i; + } + + private void checkIncrementRange(int incr, int type, int idxPos) throws ParseException { + if (incr > 59 && (type == SECOND || type == MINUTE)) { + throw new ParseException("Increment > 60 : " + incr, idxPos); + } else if (incr > 23 && (type == HOUR)) { + throw new ParseException("Increment > 24 : " + incr, idxPos); + } else if (incr > 31 && (type == DAY_OF_MONTH)) { + throw new ParseException("Increment > 31 : " + incr, idxPos); + } else if (incr > 7 && (type == DAY_OF_WEEK)) { + throw new ParseException("Increment > 7 : " + incr, idxPos); + } else if (incr > 12 && (type == MONTH)) { + throw new ParseException("Increment > 12 : " + incr, idxPos); + } + } + + protected int checkNext(int pos, String s, int val, int type) + throws ParseException { + + int end = -1; + int i = pos; + + if (i >= s.length()) { + addToSet(val, end, -1, type); + return i; + } + + char c = s.charAt(pos); + + if (c == 'L') { + if (type == DAY_OF_WEEK) { + if(val < 1 || val > 7) + throw new ParseException("Day-of-Week values must be between 1 and 7", -1); + lastdayOfWeek = true; + } else { + throw new ParseException("'L' option is not valid here. (pos=" + i + ")", i); + } + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == 'W') { + if (type == DAY_OF_MONTH) { + nearestWeekday = true; + } else { + throw new ParseException("'W' option is not valid here. (pos=" + i + ")", i); + } + if(val > 31) + throw new ParseException("The 'W' option does not make sense with values larger than 31 (max number of days in a month)", i); + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == '#') { + if (type != DAY_OF_WEEK) { + throw new ParseException("'#' option is not valid here. (pos=" + i + ")", i); + } + i++; + try { + nthdayOfWeek = Integer.parseInt(s.substring(i)); + if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + throw new Exception(); + } + } catch (Exception e) { + throw new ParseException( + "A numeric value between 1 and 5 must follow the '#' option", + i); + } + + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == '-') { + i++; + c = s.charAt(i); + int v = Integer.parseInt(String.valueOf(c)); + end = v; + i++; + if (i >= s.length()) { + addToSet(val, end, 1, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v, s, i); + end = vs.value; + i = vs.pos; + } + if (i < s.length() && ((c = s.charAt(i)) == '/')) { + i++; + c = s.charAt(i); + int v2 = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + addToSet(val, end, v2, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v2, s, i); + int v3 = vs.value; + addToSet(val, end, v3, type); + i = vs.pos; + return i; + } else { + addToSet(val, end, v2, type); + return i; + } + } else { + addToSet(val, end, 1, type); + return i; + } + } + + if (c == '/') { + if ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s.charAt(i + 1) == '\t') { + throw new ParseException("'/' must be followed by an integer.", i); + } + + i++; + c = s.charAt(i); + int v2 = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + checkIncrementRange(v2, type, i); + addToSet(val, end, v2, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v2, s, i); + int v3 = vs.value; + checkIncrementRange(v3, type, i); + addToSet(val, end, v3, type); + i = vs.pos; + return i; + } else { + throw new ParseException("Unexpected character '" + c + "' after '/'", i); + } + } + + addToSet(val, end, 0, type); + i++; + return i; + } + + public String getCronExpression() { + return cronExpression; + } + + public String getExpressionSummary() { + StringBuilder buf = new StringBuilder(); + + buf.append("seconds: "); + buf.append(getExpressionSetSummary(seconds)); + buf.append("\n"); + buf.append("minutes: "); + buf.append(getExpressionSetSummary(minutes)); + buf.append("\n"); + buf.append("hours: "); + buf.append(getExpressionSetSummary(hours)); + buf.append("\n"); + buf.append("daysOfMonth: "); + buf.append(getExpressionSetSummary(daysOfMonth)); + buf.append("\n"); + buf.append("months: "); + buf.append(getExpressionSetSummary(months)); + buf.append("\n"); + buf.append("daysOfWeek: "); + buf.append(getExpressionSetSummary(daysOfWeek)); + buf.append("\n"); + buf.append("lastdayOfWeek: "); + buf.append(lastdayOfWeek); + buf.append("\n"); + buf.append("nearestWeekday: "); + buf.append(nearestWeekday); + buf.append("\n"); + buf.append("NthDayOfWeek: "); + buf.append(nthdayOfWeek); + buf.append("\n"); + buf.append("lastdayOfMonth: "); + buf.append(lastdayOfMonth); + buf.append("\n"); + buf.append("years: "); + buf.append(getExpressionSetSummary(years)); + buf.append("\n"); + + return buf.toString(); + } + + protected String getExpressionSetSummary(Set set) { + + if (set.contains(NO_SPEC)) { + return "?"; + } + if (set.contains(ALL_SPEC)) { + return "*"; + } + + StringBuilder buf = new StringBuilder(); + + Iterator itr = set.iterator(); + boolean first = true; + while (itr.hasNext()) { + Integer iVal = itr.next(); + String val = iVal.toString(); + if (!first) { + buf.append(","); + } + buf.append(val); + first = false; + } + + return buf.toString(); + } + + protected String getExpressionSetSummary(ArrayList list) { + + if (list.contains(NO_SPEC)) { + return "?"; + } + if (list.contains(ALL_SPEC)) { + return "*"; + } + + StringBuilder buf = new StringBuilder(); + + Iterator itr = list.iterator(); + boolean first = true; + while (itr.hasNext()) { + Integer iVal = itr.next(); + String val = iVal.toString(); + if (!first) { + buf.append(","); + } + buf.append(val); + first = false; + } + + return buf.toString(); + } + + protected int skipWhiteSpace(int i, String s) { + for (; i < s.length() && (s.charAt(i) == ' ' || s.charAt(i) == '\t'); i++) { + ; + } + + return i; + } + + protected int findNextWhiteSpace(int i, String s) { + for (; i < s.length() && (s.charAt(i) != ' ' || s.charAt(i) != '\t'); i++) { + ; + } + + return i; + } + + protected void addToSet(int val, int end, int incr, int type) + throws ParseException { + + TreeSet set = getSet(type); + + if (type == SECOND || type == MINUTE) { + if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Minute and Second values must be between 0 and 59", + -1); + } + } else if (type == HOUR) { + if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Hour values must be between 0 and 23", -1); + } + } else if (type == DAY_OF_MONTH) { + if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT) + && (val != NO_SPEC_INT)) { + throw new ParseException( + "Day of month values must be between 1 and 31", -1); + } + } else if (type == MONTH) { + if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Month values must be between 1 and 12", -1); + } + } else if (type == DAY_OF_WEEK) { + if ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT) + && (val != NO_SPEC_INT)) { + throw new ParseException( + "Day-of-Week values must be between 1 and 7", -1); + } + } + + if ((incr == 0 || incr == -1) && val != ALL_SPEC_INT) { + if (val != -1) { + set.add(val); + } else { + set.add(NO_SPEC); + } + + return; + } + + int startAt = val; + int stopAt = end; + + if (val == ALL_SPEC_INT && incr <= 0) { + incr = 1; + set.add(ALL_SPEC); // put in a marker, but also fill values + } + + if (type == SECOND || type == MINUTE) { + if (stopAt == -1) { + stopAt = 59; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 0; + } + } else if (type == HOUR) { + if (stopAt == -1) { + stopAt = 23; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 0; + } + } else if (type == DAY_OF_MONTH) { + if (stopAt == -1) { + stopAt = 31; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == MONTH) { + if (stopAt == -1) { + stopAt = 12; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == DAY_OF_WEEK) { + if (stopAt == -1) { + stopAt = 7; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == YEAR) { + if (stopAt == -1) { + stopAt = MAX_YEAR; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1970; + } + } + + // if the end of the range is before the start, then we need to overflow into + // the next day, month etc. This is done by adding the maximum amount for that + // type, and using modulus max to determine the value being added. + int max = -1; + if (stopAt < startAt) { + switch (type) { + case SECOND : max = 60; break; + case MINUTE : max = 60; break; + case HOUR : max = 24; break; + case MONTH : max = 12; break; + case DAY_OF_WEEK : max = 7; break; + case DAY_OF_MONTH : max = 31; break; + case YEAR : throw new IllegalArgumentException("Start year must be less than stop year"); + default : throw new IllegalArgumentException("Unexpected type encountered"); + } + stopAt += max; + } + + for (int i = startAt; i <= stopAt; i += incr) { + if (max == -1) { + // ie: there's no max to overflow over + set.add(i); + } else { + // take the modulus to get the real value + int i2 = i % max; + + // 1-indexed ranges should not include 0, and should include their max + if (i2 == 0 && (type == MONTH || type == DAY_OF_WEEK || type == DAY_OF_MONTH) ) { + i2 = max; + } + + set.add(i2); + } + } + } + + TreeSet getSet(int type) { + switch (type) { + case SECOND: + return seconds; + case MINUTE: + return minutes; + case HOUR: + return hours; + case DAY_OF_MONTH: + return daysOfMonth; + case MONTH: + return months; + case DAY_OF_WEEK: + return daysOfWeek; + case YEAR: + return years; + default: + return null; + } + } + + protected ValueSet getValue(int v, String s, int i) { + char c = s.charAt(i); + StringBuilder s1 = new StringBuilder(String.valueOf(v)); + while (c >= '0' && c <= '9') { + s1.append(c); + i++; + if (i >= s.length()) { + break; + } + c = s.charAt(i); + } + ValueSet val = new ValueSet(); + + val.pos = (i < s.length()) ? i : i + 1; + val.value = Integer.parseInt(s1.toString()); + return val; + } + + protected int getNumericValue(String s, int i) { + int endOfVal = findNextWhiteSpace(i, s); + String val = s.substring(i, endOfVal); + return Integer.parseInt(val); + } + + protected int getMonthNumber(String s) { + Integer integer = monthMap.get(s); + + if (integer == null) { + return -1; + } + + return integer; + } + + protected int getDayOfWeekNumber(String s) { + Integer integer = dayMap.get(s); + + if (integer == null) { + return -1; + } + + return integer; + } + + //////////////////////////////////////////////////////////////////////////// + // + // Computation Functions + // + //////////////////////////////////////////////////////////////////////////// + + public Date getTimeAfter(Date afterTime) { + + // Computation is based on Gregorian year only. + Calendar cl = new GregorianCalendar(getTimeZone()); + + // move ahead one second, since we're computing the time *after* the + // given time + afterTime = new Date(afterTime.getTime() + 1000); + // CronTrigger does not deal with milliseconds + cl.setTime(afterTime); + cl.set(Calendar.MILLISECOND, 0); + + boolean gotOne = false; + // loop until we've computed the next time, or we've past the endTime + while (!gotOne) { + + //if (endTime != null && cl.getTime().after(endTime)) return null; + if(cl.get(Calendar.YEAR) > 2999) { // prevent endless loop... + return null; + } + + SortedSet st = null; + int t = 0; + + int sec = cl.get(Calendar.SECOND); + int min = cl.get(Calendar.MINUTE); + + // get second................................................. + st = seconds.tailSet(sec); + if (st != null && st.size() != 0) { + sec = st.first(); + } else { + sec = seconds.first(); + min++; + cl.set(Calendar.MINUTE, min); + } + cl.set(Calendar.SECOND, sec); + + min = cl.get(Calendar.MINUTE); + int hr = cl.get(Calendar.HOUR_OF_DAY); + t = -1; + + // get minute................................................. + st = minutes.tailSet(min); + if (st != null && st.size() != 0) { + t = min; + min = st.first(); + } else { + min = minutes.first(); + hr++; + } + if (min != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, min); + setCalendarHour(cl, hr); + continue; + } + cl.set(Calendar.MINUTE, min); + + hr = cl.get(Calendar.HOUR_OF_DAY); + int day = cl.get(Calendar.DAY_OF_MONTH); + t = -1; + + // get hour................................................... + st = hours.tailSet(hr); + if (st != null && st.size() != 0) { + t = hr; + hr = st.first(); + } else { + hr = hours.first(); + day++; + } + if (hr != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + setCalendarHour(cl, hr); + continue; + } + cl.set(Calendar.HOUR_OF_DAY, hr); + + day = cl.get(Calendar.DAY_OF_MONTH); + int mon = cl.get(Calendar.MONTH) + 1; + // '+ 1' because calendar is 0-based for this field, and we are + // 1-based + t = -1; + int tmon = mon; + + // get day................................................... + boolean dayOfMSpec = !daysOfMonth.contains(NO_SPEC); + boolean dayOfWSpec = !daysOfWeek.contains(NO_SPEC); + if (dayOfMSpec && !dayOfWSpec) { // get day by day of month rule + st = daysOfMonth.tailSet(day); + if (lastdayOfMonth) { + if(!nearestWeekday) { + t = day; + day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day -= lastdayOffset; + if(t > day) { + mon++; + if(mon > 12) { + mon = 1; + tmon = 3333; // ensure test of mon != tmon further below fails + cl.add(Calendar.YEAR, 1); + } + day = 1; + } + } else { + t = day; + day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day -= lastdayOffset; + + Calendar tcal = Calendar.getInstance(getTimeZone()); + tcal.set(Calendar.SECOND, 0); + tcal.set(Calendar.MINUTE, 0); + tcal.set(Calendar.HOUR_OF_DAY, 0); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); + + int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int dow = tcal.get(Calendar.DAY_OF_WEEK); + + if(dow == Calendar.SATURDAY && day == 1) { + day += 2; + } else if(dow == Calendar.SATURDAY) { + day -= 1; + } else if(dow == Calendar.SUNDAY && day == ldom) { + day -= 2; + } else if(dow == Calendar.SUNDAY) { + day += 1; + } + + tcal.set(Calendar.SECOND, sec); + tcal.set(Calendar.MINUTE, min); + tcal.set(Calendar.HOUR_OF_DAY, hr); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + Date nTime = tcal.getTime(); + if(nTime.before(afterTime)) { + day = 1; + mon++; + } + } + } else if(nearestWeekday) { + t = day; + day = daysOfMonth.first(); + + Calendar tcal = Calendar.getInstance(getTimeZone()); + tcal.set(Calendar.SECOND, 0); + tcal.set(Calendar.MINUTE, 0); + tcal.set(Calendar.HOUR_OF_DAY, 0); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); + + int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int dow = tcal.get(Calendar.DAY_OF_WEEK); + + if(dow == Calendar.SATURDAY && day == 1) { + day += 2; + } else if(dow == Calendar.SATURDAY) { + day -= 1; + } else if(dow == Calendar.SUNDAY && day == ldom) { + day -= 2; + } else if(dow == Calendar.SUNDAY) { + day += 1; + } + + + tcal.set(Calendar.SECOND, sec); + tcal.set(Calendar.MINUTE, min); + tcal.set(Calendar.HOUR_OF_DAY, hr); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + Date nTime = tcal.getTime(); + if(nTime.before(afterTime)) { + day = daysOfMonth.first(); + mon++; + } + } else if (st != null && st.size() != 0) { + t = day; + day = st.first(); + // make sure we don't over-run a short month, such as february + int lastDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + if (day > lastDay) { + day = daysOfMonth.first(); + mon++; + } + } else { + day = daysOfMonth.first(); + mon++; + } + + if (day != t || mon != tmon) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we + // are 1-based + continue; + } + } else if (dayOfWSpec && !dayOfMSpec) { // get day by day of week rule + if (lastdayOfWeek) { // are we looking for the last XXX day of + // the month? + int dow = daysOfWeek.first(); // desired + // d-o-w + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } + if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + + if (day + daysToAdd > lDay) { // did we already miss the + // last one? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } + + // find date of last occurrence of this day in this month... + while ((day + daysToAdd + 7) <= lDay) { + daysToAdd += 7; + } + + day += daysToAdd; + + if (daysToAdd > 0) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' here because we are not promoting the month + continue; + } + + } else if (nthdayOfWeek != 0) { + // are we looking for the Nth XXX day in the month? + int dow = daysOfWeek.first(); // desired + // d-o-w + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } else if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + boolean dayShifted = false; + if (daysToAdd > 0) { + dayShifted = true; + } + + day += daysToAdd; + int weekOfMonth = day / 7; + if (day % 7 > 0) { + weekOfMonth++; + } + + daysToAdd = (nthdayOfWeek - weekOfMonth) * 7; + day += daysToAdd; + if (daysToAdd < 0 + || day > getLastDayOfMonth(mon, cl + .get(Calendar.YEAR))) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } else if (daysToAdd > 0 || dayShifted) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' here because we are NOT promoting the month + continue; + } + } else { + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int dow = daysOfWeek.first(); // desired + // d-o-w + st = daysOfWeek.tailSet(cDow); + if (st != null && st.size() > 0) { + dow = st.first(); + } + + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } + if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + + if (day + daysToAdd > lDay) { // will we pass the end of + // the month? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } else if (daysToAdd > 0) { // are we swithing days? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day + daysToAdd); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, + // and we are 1-based + continue; + } + } + } else { // dayOfWSpec && !dayOfMSpec + throw new UnsupportedOperationException( + "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented."); + } + cl.set(Calendar.DAY_OF_MONTH, day); + + mon = cl.get(Calendar.MONTH) + 1; + // '+ 1' because calendar is 0-based for this field, and we are + // 1-based + int year = cl.get(Calendar.YEAR); + t = -1; + + // test for expressions that never generate a valid fire date, + // but keep looping... + if (year > MAX_YEAR) { + return null; + } + + // get month................................................... + st = months.tailSet(mon); + if (st != null && st.size() != 0) { + t = mon; + mon = st.first(); + } else { + mon = months.first(); + year++; + } + if (mon != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + cl.set(Calendar.YEAR, year); + continue; + } + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + + year = cl.get(Calendar.YEAR); + t = -1; + + // get year................................................... + st = years.tailSet(year); + if (st != null && st.size() != 0) { + t = year; + year = st.first(); + } else { + return null; // ran out of years... + } + + if (year != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, 0); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + cl.set(Calendar.YEAR, year); + continue; + } + cl.set(Calendar.YEAR, year); + + gotOne = true; + } // while( !done ) + + return cl.getTime(); + } + + /** + * Advance the calendar to the particular hour paying particular attention + * to daylight saving problems. + * + * @param cal the calendar to operate on + * @param hour the hour to set + */ + protected void setCalendarHour(Calendar cal, int hour) { + cal.set(Calendar.HOUR_OF_DAY, hour); + if (cal.get(Calendar.HOUR_OF_DAY) != hour && hour != 24) { + cal.set(Calendar.HOUR_OF_DAY, hour + 1); + } + } + + /** + * NOT YET IMPLEMENTED: Returns the time before the given time + * that the CronExpression matches. + */ + public Date getTimeBefore(Date endTime) { + // FUTURE_TODO: implement QUARTZ-423 + return null; + } + + /** + * NOT YET IMPLEMENTED: Returns the final time that the + * CronExpression will match. + */ + public Date getFinalFireTime() { + // FUTURE_TODO: implement QUARTZ-423 + return null; + } + + protected boolean isLeapYear(int year) { + return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)); + } + + protected int getLastDayOfMonth(int monthNum, int year) { + + switch (monthNum) { + case 1: + return 31; + case 2: + return (isLeapYear(year)) ? 29 : 28; + case 3: + return 31; + case 4: + return 30; + case 5: + return 31; + case 6: + return 30; + case 7: + return 31; + case 8: + return 31; + case 9: + return 30; + case 10: + return 31; + case 11: + return 30; + case 12: + return 31; + default: + throw new IllegalArgumentException("Illegal month number: " + + monthNum); + } + } + + + private void readObject(java.io.ObjectInputStream stream) + throws java.io.IOException, ClassNotFoundException { + + stream.defaultReadObject(); + try { + buildExpression(cronExpression); + } catch (Exception ignore) { + } // never happens + } + +} + +class ValueSet { + public int value; + + public int pos; +} + diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java new file mode 100644 index 000000000..f674f602e --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java @@ -0,0 +1,340 @@ +package com.newrelic.agent.security.intcodeagent.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.HttpRequest; +import com.newrelic.api.agent.security.schema.policy.MappingParameters; +import com.newrelic.api.agent.security.schema.policy.RestrictionCriteria; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.StringReader; +import java.util.*; + +public class RestrictionUtility { + + public static final String SEPARATOR_CHARS_QUESTION_MARK = "?"; + public static final String SEPARATOR_CHARS_SEMICOLON = ";"; + public static final String FORWARD_SLASH = "/"; + public static final String AND = "&"; + public static final String SEPARATOR_EQUALS = "="; + public static final String EQUAL = "="; + public static final String CONTENT_TYPE_TEXT_JSON = "text/json"; + public static final String CONTENT_TYPE_TEXT_XML = "text/xml"; + public static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; + public static final String CONTENT_TYPE_APPLICATION_XML = "application/xml"; + public static final String CONTENT_TYPE_APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded"; + + private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); + + public static boolean hasValidAccountId(RestrictionCriteria restrictionCriteria, HttpRequest request) { + String accountId = restrictionCriteria.getAccountInfo().getAccountId(); + if (request == null) { + return false; + } + if(!request.isRequestParametersParsed()){ + parseHttpRequestParameters(request); + } + for (MappingParameters mappingParameter : restrictionCriteria.getMappingParameters()) { + boolean match = false; + switch (mappingParameter.getAccountIdLocation()) { + case QUERY: + List queryParameters = getQueryString(mappingParameter.getAccountIdKey(), request.getQueryParameters()); + match = matcher(accountId, queryParameters); + break; + case PATH: + match = matcher(accountId, request.getPathParameters()); + break; + case HEADER: + List headerValues = getHeaderParameters(mappingParameter.getAccountIdKey(), request.getRequestHeaderParameters()); + match = matcher(accountId, headerValues); + break; + case BODY: + List bodyValues = getBodyParameters(mappingParameter.getAccountIdKey(), request.getRequestBodyParameters()); + match = matcher(accountId, bodyValues); + break; + } + if(match){ + return true; + } + } + return false; + } + + private static List getBodyParameters(String accountId, Map> requestBodyParameters) { + if (requestBodyParameters == null || requestBodyParameters.isEmpty()) { + return Collections.emptyList(); + } + String lowerCaseAccountId = accountId.toLowerCase(); + return requestBodyParameters.get(lowerCaseAccountId); + } + + private static List getHeaderParameters(String accountId, Map> requestHeaderParameters) { + if (requestHeaderParameters == null || requestHeaderParameters.isEmpty()) { + return Collections.emptyList(); + } + String lowerCaseAccountId = accountId.toLowerCase(); + return requestHeaderParameters.get(lowerCaseAccountId); + } + + private static List getQueryString(String accountId, Map> queryParameters) { + if(queryParameters == null || queryParameters.isEmpty()) { + return Collections.emptyList(); + } + String lowerCaseAccountId = accountId.toLowerCase(); + return queryParameters.get(lowerCaseAccountId); + } + + private static boolean matcher(String accountId, List values) { + if(values == null || values.isEmpty() || StringUtils.isBlank(accountId)) { + return false; + } + String lowerCaseAccountId = accountId.toLowerCase(); + return values.contains(lowerCaseAccountId); + } + + private static void parseHttpRequestParameters(HttpRequest request) { + request.setPathParameters(parsePathParameters(StringUtils.substringBefore(request.getUrl(), + SEPARATOR_CHARS_QUESTION_MARK))); + request.setQueryParameters(parseQueryParameters(request.getUrl())); + request.setRequestHeaderParameters(parseRequestHeaders(request.getHeaders())); + request.setRequestBodyParameters(parseRequestBody(request.getBody(), request.getContentType(), request.getRequestBodyParameters())); + request.setRequestBodyParameters(parseRequestParameterMap(request.getParameterMap(), request.getRequestBodyParameters())); + request.setRequestParsed(true); + } + + private static Map> parseRequestParameterMap(Map parameterMap, Map> requestBodyParameters) { + if(parameterMap == null) { + return requestBodyParameters; + } + if(requestBodyParameters == null) { + requestBodyParameters = new HashMap<>(); + } + + for (Map.Entry entry : parameterMap.entrySet()) { + String key = entry.getKey(); + String[] values = entry.getValue(); + List valuesList = new ArrayList<>(); + for (String value : values) { + valuesList.add(StringUtils.lowerCase(value)); + } + if(requestBodyParameters.containsKey(key)){ + requestBodyParameters.get(key).addAll(valuesList); + } else { + requestBodyParameters.put(key, valuesList); + } + } + return requestBodyParameters; + } + + private static Map> parseRequestBody(StringBuilder body, String contentType, Map> requestBodyParameters) { + if(StringUtils.isBlank(body.toString())) { + return requestBodyParameters; + } + + if(requestBodyParameters == null) { + requestBodyParameters = new HashMap<>(); + } + + switch (contentType) { + case CONTENT_TYPE_APPLICATION_JSON: + case CONTENT_TYPE_TEXT_JSON: + requestBodyParameters.putAll(parseJsonRequestBody(body.toString())); + break; + case CONTENT_TYPE_APPLICATION_XML: + case CONTENT_TYPE_TEXT_XML: + requestBodyParameters.putAll(parseXmlRequestBody(body.toString())); + break; + case CONTENT_TYPE_APPLICATION_X_WWW_FORM_URLENCODED: + requestBodyParameters.putAll(queryParamKeyValueGenerator(body.toString(),new HashMap<>())); + break; + default: + break; + } + return requestBodyParameters; + + } + + private static Map> parseXmlRequestBody(String body) { + //write logic to xml parsing + Map> requestBodyParameters = new HashMap<>(); + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.parse(new InputSource(new StringReader(body))); + document.getDocumentElement().normalize(); + Element root = document.getDocumentElement(); + parseXmlNode(root, StringUtils.EMPTY, requestBodyParameters); + } catch (Exception e) { + // TODO: log error + } + return requestBodyParameters; + } + + private static void parseXmlNode(Node node, String baseKey, Map> requestBodyParameters) { + if (node.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) node; + NodeList children = element.getChildNodes(); + String key = baseKey.isEmpty() ? element.getTagName() : baseKey + "." + element.getTagName(); + if (children.getLength() == 1 && children.item(0).getNodeType() == Node.TEXT_NODE) { + String value = children.item(0).getTextContent().trim(); + if (!value.isEmpty()) { + requestBodyParameters.computeIfAbsent(key, k -> new ArrayList<>()).add(value); + } + } else { + for (int i = 0; i < children.getLength(); i++) { + parseXmlNode(children.item(i), key, requestBodyParameters); + } + } + } + } + + private static Map> parseJsonRequestBody(String body) { + JsonNode node; + ObjectMapper mapper = new ObjectMapper(); + try { + node = mapper.readValue(body, JsonNode.class); + Map> requestBodyParameters = new HashMap<>(); + return parseJsonNode(node, StringUtils.EMPTY, requestBodyParameters); + } catch (JsonProcessingException e) { + //TODO log error + } + return Collections.emptyMap(); + + } + + private static Map> parseJsonNode(JsonNode node, String baseKey, Map> requestBodyParameters) { + if (node.isObject()) { + Iterator> iterator = node.fields(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + String key = entry.getKey(); + String base = getBase(baseKey, key); + JsonNode value = entry.getValue(); + if(value.isContainerNode()){ + parseJsonNode(value, base, requestBodyParameters); + } else if (StringUtils.isNotBlank(value.asText())) { + if(!requestBodyParameters.containsKey(base)){ + requestBodyParameters.put(base, new ArrayList<>()); + } + requestBodyParameters.get(base).add(value.asText()); + } + } + } else if (node.isArray()) { + ArrayNode arrayNode = (ArrayNode) node; + for (int i = 0; i < arrayNode.size(); i++) { + JsonNode jsonNode = arrayNode.get(i); + String base = getBase(baseKey, i); + if(jsonNode.isContainerNode()){ + parseJsonNode(jsonNode, base, requestBodyParameters); + } else if (StringUtils.isNotBlank(jsonNode.asText())) { + if(!requestBodyParameters.containsKey(base)){ + requestBodyParameters.put(base, new ArrayList<>()); + } + requestBodyParameters.get(base).add(jsonNode.asText()); + } + } + } + return requestBodyParameters; + } + + private static @NotNull String getBase(String baseKey, String key) { + if(StringUtils.isBlank(baseKey)){ + return key; + } + return baseKey + "." + key; + } + + private static @NotNull String getBase(String baseKey, int index) { + if(StringUtils.isBlank(baseKey)){ + return String.format("[%s]", index); + } + return String.format("%s[%s]", baseKey, index); + } + + private static Map> parseRequestHeaders(Map headers) { + Map> requestHeaderParameters = new HashMap<>(); + for (Map.Entry header : headers.entrySet()) { + String key = header.getKey(); + String value = header.getValue(); + putHeaderParameter(key, value, requestHeaderParameters); + if (StringUtils.containsAny(value, SEPARATOR_CHARS_SEMICOLON, EQUAL)) { + String[] headerKeyValues = value.split(SEPARATOR_CHARS_SEMICOLON); + for (int i = 0; i < headerKeyValues.length; i++) { + if (StringUtils.contains(headerKeyValues[i], EQUAL) + && !StringUtils.endsWith(headerKeyValues[i], EQUAL)) { + String headerKey = StringUtils.substringBefore(headerKeyValues[i], EQUAL).trim(); + String headerValue = StringUtils.substringAfter(headerKeyValues[i], EQUAL).trim(); + putHeaderParameter(headerKey, headerValue, requestHeaderParameters); + } else { + putHeaderParameter(key, headerKeyValues[i], requestHeaderParameters); + } + } + } + } + return requestHeaderParameters; + } + + private static void putHeaderParameter(String key, String value, Map> requestHeaderParameters) { + List headerValues = requestHeaderParameters.get(key); + if (headerValues == null) { + headerValues = new ArrayList<>(); + } + headerValues.add(StringUtils.lowerCase(value)); + headerValues.add(StringUtils.lowerCase(ServletHelper.urlDecode(value))); + requestHeaderParameters.put(key, headerValues); + } + + private static Map> parseQueryParameters(String url) { + Map> queryParameters = new HashMap<>(); + String query = StringUtils.substringAfter(url, SEPARATOR_CHARS_QUESTION_MARK); + if (StringUtils.isNotBlank(query)) { + queryParamKeyValueGenerator(query, queryParameters); + } else { + query = StringUtils.substringAfter(url, SEPARATOR_CHARS_SEMICOLON); + if (StringUtils.isNotBlank(query)) { + queryParamKeyValueGenerator(query, queryParameters); + } + } + return queryParameters; + } + + private static Map> queryParamKeyValueGenerator(String query, Map> queryParameters) { + String[] queryParams = StringUtils.split(query, AND); + for (String queryParam : queryParams) { + String key, value; + key = StringUtils.substringBefore(queryParam, SEPARATOR_EQUALS); + value = StringUtils.substringAfter(queryParam, SEPARATOR_EQUALS); + List values = new ArrayList<>(); + values.add(StringUtils.lowerCase(value)); + values.add(StringUtils.lowerCase(ServletHelper.urlDecode(value))); + queryParameters.put(key, values); + } + return queryParameters; + } + + private static List parsePathParameters(String uri) { + List pathParameters = new ArrayList<>(); + String requestPath = StringUtils.substringBefore(uri, + SEPARATOR_CHARS_SEMICOLON); + if(StringUtils.isNotBlank(requestPath)) { + String[] pathVariables = StringUtils.split(requestPath, FORWARD_SLASH); + for (String pathVariable : pathVariables) { + pathParameters.add(StringUtils.lowerCase(pathVariable)); + pathParameters.add(StringUtils.lowerCase(ServletHelper.urlDecode(pathVariable))); + } + } + return pathParameters; + } +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java index d940d5844..dcf24e7af 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java @@ -91,7 +91,7 @@ public void sendEvent(JavaAgentEventBean event) { AgentInfo.getInstance().getJaHealthCheck().incrementEventSendRejectionCount(); return; } - executor.submit(new EventSender(event)); + Future f = executor.submit(new EventSender(event)); AgentInfo.getInstance().getJaHealthCheck().incrementEventSentCount(); } 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 64f1ffcfd..09986e15b 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 @@ -347,16 +347,22 @@ public static WSClient reconnectWSClient() throws URISyntaxException, Interrupte return instance; } - public static void shutDownWSClient(boolean clean) { + public static void shutDownWSClientAbnormal(boolean clean) { logger.log(LogLevel.WARNING, "Disconnecting WS client forced by APM", WSClient.class.getName()); + shutDownWSClient(clean, CloseFrame.ABNORMAL_CLOSE, "Client disconnecting forced by APM"); + } + + public static void shutDownWSClient(boolean clean, int frame, String message) { + logger.log(LogLevel.WARNING, String.format("WebSocket Shutdown initiated with %s", frame), + WSClient.class.getName()); WSUtils.getInstance().setConnected(false); if(clean) { RestRequestThreadPool.getInstance().resetIASTProcessing(); GrpcClientRequestReplayHelper.getInstance().resetIASTProcessing(); } if (instance != null) { - instance.close(CloseFrame.ABNORMAL_CLOSE, "Client disconnecting forced by APM"); + instance.close(frame, message); } } 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 8764c0b62..bec8860eb 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 @@ -6,6 +6,21 @@ public interface IUtilConstants { String RASP = "RASP"; String IAST = "IAST"; + String IAST_RESTRICTED = "IAST_RESTRICTED"; + + String RESTRICTION_CRITERIA_SCAN_TIME = "security.restriction_criteria.scan_time"; + String RESTRICTION_CRITERIA_SCAN_TIME_SCHEDULE = "security.restriction_criteria.scan_time.schedule"; + String RESTRICTION_CRITERIA_SCAN_TIME_DURATION = "security.restriction_criteria.scan_time.duration"; + String RESTRICTION_CRITERIA = "security.restriction_criteria"; + String RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID = "security.restriction_criteria.account_info.account_id"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS = "security.restriction_criteria.mapping_parameters"; + String RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS = "security.restriction_criteria.skip_scan_parameters"; + String RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_HEADER = "security.restriction_criteria.skip_scan_parameters.header"; + String RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_QUERY = "security.restriction_criteria.skip_scan_parameters.query"; + String RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_BODY = "security.restriction_criteria.skip_scan_parameters.body"; + String RESTRICTION_CRITERIA_STRICT = "security.restriction_criteria.strict"; + + String GROUP_NAME = "group-name"; String INFO = "INFO"; String K_2_LOG_LEVEL = "K2_LOG_LEVEL"; 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 ab468d430..3f1d40827 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 @@ -12,6 +12,7 @@ import com.newrelic.agent.security.intcodeagent.filelogging.LogFileHelper; import com.newrelic.agent.security.intcodeagent.models.javaagent.*; import com.newrelic.agent.security.intcodeagent.utils.EncryptorUtils; +import com.newrelic.agent.security.intcodeagent.utils.RestrictionUtility; import com.newrelic.agent.security.intcodeagent.utils.RuntimeErrorReporter; import com.newrelic.api.agent.security.instrumentation.helpers.*; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -29,8 +30,6 @@ import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -39,6 +38,7 @@ import java.net.HttpURLConnection; import java.net.URL; import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -92,7 +92,18 @@ private Agent(){ } private void initialise() { - // TODO: All the bring up tasks are to be performed here. + + if (!isInitialised()) { + config = AgentConfig.getInstance(); + info = AgentInfo.getInstance(); + } + long delay = config.instantiate(); + SchedulerHelper.getInstance().scheduleIastTrigger(this::triggerNrSecurity, delay, TimeUnit.MILLISECONDS); + } + + private void triggerNrSecurity() { + // All the bring up tasks are to be performed here. + /* * * 1. populate policy * 2. create application info @@ -101,11 +112,6 @@ private void initialise() { * */ //NOTE: The bellow call sequence is critical and dependent on each other - if (!isInitialised()) { - config = AgentConfig.getInstance(); - info = AgentInfo.getInstance(); - } - config.instantiate(); logger = FileLoggerThreadPool.getInstance(); logger.logInit( LogLevel.INFO, @@ -145,6 +151,24 @@ private void initialise() { populateApplicationTmpDir(); startK2Services(); info.agentStatTrigger(true); + //Schedule NR csec shutdown if required + scheduleShutdownTrigger(); + } + + private void scheduleShutdownTrigger() { + if(AgentConfig.getInstance().getAgentMode().getIastScan().getEnabled() && AgentConfig.getInstance().getAgentMode().getIastScan().getRestricted()){ + int duration = AgentConfig.getInstance().getAgentMode().getIastScan().getRestrictionCriteria().getScanTime().getDuration(); + Instant now = Instant.now(); + Instant shutdownInstant = now.plus(duration, ChronoUnit.HOURS); + long shutdownTime = shutdownInstant.getEpochSecond() - now.getEpochSecond(); + SchedulerHelper.getInstance().scheduleIastTrigger(this::IastRestrictedShutdown, shutdownTime, TimeUnit.SECONDS); + } + } + + private void IastRestrictedShutdown() { + InstrumentationUtils.shutdownLogic(); + long delay = config.trigerIAST(); + SchedulerHelper.getInstance().scheduleIastTrigger(this::triggerNrSecurity, delay, TimeUnit.MILLISECONDS); } private void populateApplicationTmpDir() { @@ -222,7 +246,7 @@ private void cancelActiveServiceTasks() { * policy * HealthCheck */ - WSClient.shutDownWSClient(false); + WSClient.shutDownWSClientAbnormal(false); HealthCheckScheduleThread.getInstance().cancelTask(true); FileCleaner.cancelTask(); @@ -245,9 +269,10 @@ private void deactivateSecurityServices(){ * 3. event pool * 4. HealthCheck **/ + InstrumentationUtils.shutdownLogic(); HealthCheckScheduleThread.getInstance().cancelTask(true); FileCleaner.cancelTask(); - WSClient.shutDownWSClient(true); + WSClient.shutDownWSClientAbnormal(true); WSReconnectionST.shutDownPool(); EventSendPool.shutDownPool(); } @@ -313,6 +338,13 @@ public void registerOperation(AbstractOperation operation) { return; } + if(AgentConfig.getInstance().getAgentMode().getIastScan().getEnabled() && AgentConfig.getInstance().getAgentMode().getIastScan().getRestricted()) { + if(!RestrictionUtility.hasValidAccountId(AgentConfig.getInstance().getAgentMode().getIastScan().getRestrictionCriteria(), securityMetaData.getRequest())){ + return; + } + logger.log(LogLevel.FINER, String.format("Valid event for iast restricted environment : %s", operation), Agent.class.getName()); + } + logIfIastScanForFirstTime(securityMetaData.getFuzzRequestIdentifier(), securityMetaData.getRequest()); setRequiredStackTrace(operation, securityMetaData); diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java index 5b65ef0f6..82b30226d 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java @@ -1,5 +1,7 @@ package com.newrelic.api.agent.security.schema; +import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; + import java.nio.file.Paths; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -35,6 +37,21 @@ public class HttpRequest { private boolean isGrpc; private String route; + @JsonIgnore + private List pathParameters; + + @JsonIgnore + private Map> queryParameters; + + @JsonIgnore + private Map> requestHeaderParameters; + + @JsonIgnore + private Map> requestBodyParameters; + + @JsonIgnore + private boolean isRequestParametersParsed = false; + public HttpRequest() { this.clientIP = StringUtils.EMPTY; this.body = new StringBuilder(); @@ -67,6 +84,11 @@ public HttpRequest(HttpRequest servletInfo) { this.isRequestParsed = servletInfo.isRequestParsed; this.isGrpc = servletInfo.isGrpc; this.route = servletInfo.route; + this.pathParameterMap = servletInfo.pathParameterMap; + this.queryParameters = servletInfo.queryParameters; + this.requestHeaderParameters = servletInfo.requestHeaderParameters; + this.requestBodyParameters = servletInfo.requestBodyParameters; + this.isRequestParametersParsed = servletInfo.isRequestParametersParsed; } public String getMethod() { @@ -229,6 +251,46 @@ public void setRoute(String segment, boolean isAlreadyServlet) { this.route = Paths.get(this.route, formatedSegment).normalize().toString(); } } + + public List getPathParameters() { + return pathParameters; + } + + public void setPathParameters(List pathParameters) { + this.pathParameters = pathParameters; + } + + public Map> getQueryParameters() { + return queryParameters; + } + + public void setQueryParameters(Map> queryParameters) { + this.queryParameters = queryParameters; + } + + public Map> getRequestHeaderParameters() { + return requestHeaderParameters; + } + + public void setRequestHeaderParameters(Map> requestHeaderParameters) { + this.requestHeaderParameters = requestHeaderParameters; + } + + public Map> getRequestBodyParameters() { + return requestBodyParameters; + } + + public void setRequestBodyParameters(Map> requestBodyParameters) { + this.requestBodyParameters = requestBodyParameters; + } + + public boolean isRequestParametersParsed() { + return isRequestParametersParsed; + } + + public void setRequestParametersParsed(boolean requestParametersParsed) { + isRequestParametersParsed = requestParametersParsed; + } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/annotations/JsonProperty.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/annotations/JsonProperty.java new file mode 100644 index 000000000..19c0e51ed --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/annotations/JsonProperty.java @@ -0,0 +1,14 @@ +package com.newrelic.api.agent.security.schema.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface JsonProperty { + + String value() default ""; + +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/AccountInfo.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/AccountInfo.java new file mode 100644 index 000000000..0d0e679ab --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/AccountInfo.java @@ -0,0 +1,18 @@ +package com.newrelic.api.agent.security.schema.policy; + +public class AccountInfo { + + private final String accountId; + + public AccountInfo() { + this.accountId = null; + } + + public AccountInfo(String accountId) { + this.accountId = accountId; + } + + public String getAccountId() { + return accountId; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/HttpParameterLocation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/HttpParameterLocation.java new file mode 100644 index 000000000..97b40ac87 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/HttpParameterLocation.java @@ -0,0 +1,9 @@ +package com.newrelic.api.agent.security.schema.policy; + +public enum HttpParameterLocation { + + QUERY, + PATH, + HEADER, + BODY; +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java index f010cef9e..d5259effb 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java @@ -3,8 +3,10 @@ public class IASTScan { - private Boolean enabled = false; + private Boolean enabled = true; private Probing probing = new Probing(); + private Boolean restricted = false; + private RestrictionCriteria restrictionCriteria = new RestrictionCriteria(); /** * No args constructor for use in serialization @@ -36,4 +38,19 @@ public void setProbing(Probing probing) { this.probing = probing; } + public Boolean getRestricted() { + return restricted; + } + + public void setRestricted(Boolean restricted) { + this.restricted = restricted; + } + + public RestrictionCriteria getRestrictionCriteria() { + return restrictionCriteria; + } + + public void setRestrictionCriteria(RestrictionCriteria restrictionCriteria) { + this.restrictionCriteria = restrictionCriteria; + } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameters.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameters.java new file mode 100644 index 000000000..2294265ba --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameters.java @@ -0,0 +1,40 @@ +package com.newrelic.api.agent.security.schema.policy; + +import com.newrelic.api.agent.security.schema.annotations.JsonProperty; + +public class MappingParameters { + + @JsonProperty("account_id_location") + private HttpParameterLocation accountIdLocation; + + @JsonProperty("account_id_key") + private String accountIdKey; + + public MappingParameters() { + } + + public MappingParameters(HttpParameterLocation accountIdLocation) { + this.accountIdLocation = accountIdLocation; + } + + public MappingParameters(HttpParameterLocation accountIdLocation, String accountIdKey) { + this.accountIdLocation = accountIdLocation; + this.accountIdKey = accountIdKey; + } + + public HttpParameterLocation getAccountIdLocation() { + return accountIdLocation; + } + + public void setAccountIdLocation(HttpParameterLocation accountIdLocation) { + this.accountIdLocation = accountIdLocation; + } + + public String getAccountIdKey() { + return accountIdKey; + } + + public void setAccountIdKey(String accountIdKey) { + this.accountIdKey = accountIdKey; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RASPScan.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RASPScan.java new file mode 100644 index 000000000..d1d1e0f25 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RASPScan.java @@ -0,0 +1,17 @@ +package com.newrelic.api.agent.security.schema.policy; + +public class RASPScan { + + private Boolean enabled = true; + + public RASPScan() { + } + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java new file mode 100644 index 000000000..7a9e227cb --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java @@ -0,0 +1,60 @@ +package com.newrelic.api.agent.security.schema.policy; + +import java.util.ArrayList; +import java.util.List; + +public class RestrictionCriteria { + + private ScanTime scanTime = new ScanTime(); + + private AccountInfo accountInfo = new AccountInfo(); + + private List mappingParameters = new ArrayList<>(); + + private SkipScanParameters skipScanParameters = new SkipScanParameters(); + + private List strictMappings = new ArrayList<>(); + + public RestrictionCriteria() { + } + + public ScanTime getScanTime() { + return scanTime; + } + + public void setScanTime(ScanTime scanTime) { + this.scanTime = scanTime; + } + + public AccountInfo getAccountInfo() { + return accountInfo; + } + + public void setAccountInfo(AccountInfo accountInfo) { + this.accountInfo = accountInfo; + } + + public List getMappingParameters() { + return mappingParameters; + } + + public void setMappingParameters(List mappingParameters) { + this.mappingParameters = mappingParameters; + } + + public SkipScanParameters getSkipScanParameters() { + return skipScanParameters; + } + + public void setSkipScanParameters(SkipScanParameters skipScanParameters) { + this.skipScanParameters = skipScanParameters; + } + + public List getStrictMappings() { + return strictMappings; + } + + public void setStrictMappings(List strictMappings) { + this.strictMappings = strictMappings; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanTime.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanTime.java new file mode 100644 index 000000000..dd5d8901f --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanTime.java @@ -0,0 +1,39 @@ +package com.newrelic.api.agent.security.schema.policy; + +import java.util.Date; + +public class ScanTime { + + private int duration; + + private String schedule; + + private Date nextScanTime; + + public ScanTime() { + } + + public int getDuration() { + return duration; + } + + public void setDuration(int duration) { + this.duration = duration; + } + + public String getSchedule() { + return schedule; + } + + public void setSchedule(String schedule) { + this.schedule = schedule; + } + + public Date getNextScanTime() { + return nextScanTime; + } + + public void setNextScanTime(Date nextScanTime) { + this.nextScanTime = nextScanTime; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScanParameters.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScanParameters.java new file mode 100644 index 000000000..3338c9d84 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScanParameters.java @@ -0,0 +1,52 @@ +package com.newrelic.api.agent.security.schema.policy; + +import java.util.ArrayList; +import java.util.List; + +public class SkipScanParameters { + + private List header = new ArrayList<>(); + + private List query = new ArrayList<>(); + + private List body = new ArrayList<>(); + + public SkipScanParameters() { + } + + public List getHeader() { + return header; + } + + public List getQuery() { + return query; + } + + public List getBody() { + return body; + } + + public void setHeader(List header) { + this.header = header; + } + + public void setQuery(List query) { + this.query = query; + } + + public void setBody(List body) { + this.body = body; + } + + public void addHeader(String header) { + this.header.add(header); + } + + public void addQuery(String query) { + this.query.add(query); + } + + public void addBody(String body) { + this.body.add(body); + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/StrictMappings.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/StrictMappings.java new file mode 100644 index 000000000..8b26f1238 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/StrictMappings.java @@ -0,0 +1,46 @@ +package com.newrelic.api.agent.security.schema.policy; + +import java.util.regex.Pattern; + +public class StrictMappings { + + private String route; + + private HttpParameterLocation accountIdLocation; + + private String accountIdKey; + + private Pattern routePattern; + + public StrictMappings() { + } + + public String getRoute() { + return route; + } + + public void setRoute(String route) { + this.route = route; + this.routePattern = Pattern.compile(route); + } + + public HttpParameterLocation getAccountIdLocation() { + return accountIdLocation; + } + + public void setAccountIdLocation(HttpParameterLocation accountIdLocation) { + this.accountIdLocation = accountIdLocation; + } + + public String getAccountIdKey() { + return accountIdKey; + } + + public void setAccountIdKey(String accountIdKey) { + this.accountIdKey = accountIdKey; + } + + public Pattern getRoutePattern() { + return routePattern; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/VulnerabilityScan.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/VulnerabilityScan.java index 2aad4d717..1a36bf327 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/VulnerabilityScan.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/VulnerabilityScan.java @@ -3,7 +3,7 @@ public class VulnerabilityScan { - private Boolean enabled = false; + private Boolean enabled = true; private IASTScan iastScan = new IASTScan(); private Boolean enableHooks = false; From f886d56b9579205b8a0e75bfa5005918850e56dd Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 5 Aug 2024 14:25:22 +0530 Subject: [PATCH 042/122] Remove home directory mandate for running IAST agent Send expected error if home directory is missing --- .../newrelic/agent/security/AgentConfig.java | 56 +++++++++++-------- .../os/OsVariablesInstance.java | 22 +------- .../utils/InstrumentationUtils.java | 5 +- .../filelogging/FileLoggerThreadPool.java | 31 +++++++--- .../intcodeagent/schedulers/FileCleaner.java | 4 ++ .../agent/security/util/IUtilConstants.java | 1 + 6 files changed, 66 insertions(+), 53 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 af043606f..e26dc4a6c 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 @@ -23,6 +23,8 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import static com.newrelic.agent.security.util.IUtilConstants.DIRECTORY_PERMISSION; @@ -46,19 +48,15 @@ public class AgentConfig { private OSVariables osVariables; + private Map noticeErrorCustomParams = new HashMap<>(); + private AgentConfig(){ } public void instantiate(){ //Set k2 home path - 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); - } + boolean validHomePath = setK2HomePath(); + System.out.println("New Relic Security Agent: Setting csec home path to directory: "+NR_CSEC_HOME); isNRSecurityEnabled = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_ENABLED, false); // Set required Group groupName = applyRequiredGroup(); @@ -103,34 +101,41 @@ private String applyRequiredLogLevel() { return logLevel; } - public boolean setK2HomePath() throws IOException { - String agentJarLocation = NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION); - if (NewRelic.getAgent().getConfig().getValue(AGENT_HOME) != null) { + public boolean setK2HomePath(){ + noticeErrorCustomParams.put(IUtilConstants.LOG_FILE_PATH, NewRelic.getAgent().getConfig().getValue(IUtilConstants.LOG_FILE_PATH)); + noticeErrorCustomParams.put(AGENT_JAR_LOCATION, NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION)); + noticeErrorCustomParams.put(AGENT_HOME, NewRelic.getAgent().getConfig().getValue(AGENT_HOME)); + if(NewRelic.getAgent().getConfig().getValue(IUtilConstants.LOG_FILE_PATH) != null) { + NR_CSEC_HOME = NewRelic.getAgent().getConfig().getValue(IUtilConstants.LOG_FILE_PATH); + } else if (NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION) != null) { + NR_CSEC_HOME = NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION); + } else if (NewRelic.getAgent().getConfig().getValue(AGENT_HOME) != null) { + //system property `newrelic.home` or environment variable `NEWRELIC_HOME` 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 { - System.err.println("[NR-CSEC-JA] Missing or Incorrect system property `newrelic.home` or environment variable `NEWRELIC_HOME`. Collector exiting."); + NewRelic.noticeError("CSEC home directory not found. Please check the agent configs or system property `newrelic.home` or environment variable `NEWRELIC_HOME`", noticeErrorCustomParams, true); + System.err.println("[NR-CSEC-JA] CSEC home directory not found. Please check the agent configs or system property `newrelic.home` or environment variable `NEWRELIC_HOME`."); return false; } Path k2homePath = Paths.get(NR_CSEC_HOME, IUtilConstants.NR_SECURITY_HOME); - if(!CommonUtils.forceMkdirs(k2homePath, DIRECTORY_PERMISSION)){ - System.err.println(String.format("[NR-CSEC-JA] CSEC home directory creation failed at %s", NR_CSEC_HOME)); + try { + noticeErrorCustomParams.put("CSEC_HOME", k2homePath.toString()); + 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; + } + } catch (IOException e) { + NewRelic.noticeError(e, noticeErrorCustomParams, true); 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())); - 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 'newrelic.home'. Collector exiting."); - return false; - } - return true; + AgentUtils.getInstance().getStatusLogValues().put("agent-location", NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION)); + return isValidK2HomePath(NR_CSEC_HOME); } - private static boolean isValidK2HomePath(String k2Home) { + private boolean isValidK2HomePath(String k2Home) { if (StringUtils.isNotBlank(k2Home) && Paths.get(k2Home).toFile().isDirectory()) { long avail = 0; try { @@ -142,9 +147,12 @@ private static boolean isValidK2HomePath(String k2Home) { if (avail > FileUtils.ONE_GB) { return true; } + noticeErrorCustomParams.put("CSEC_HOME_DISK_AVL_BYTES", String.valueOf(avail)); + NewRelic.noticeError("Insufficient disk space available to the location " + k2Home + " is : " + FileUtils.byteCountToDisplaySize(avail), noticeErrorCustomParams, true); System.err.println(String.format("[NR-CSEC-JA] Insufficient disk space available to the location %s is : %s", k2Home, FileUtils.byteCountToDisplaySize(avail))); return false; } + NewRelic.noticeError("CSEC home directory not found :"+k2Home, noticeErrorCustomParams, true); return false; } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java index 1ce9277c0..b8448224e 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java @@ -5,6 +5,7 @@ import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; import com.newrelic.agent.security.util.IUtilConstants; import com.newrelic.api.agent.NewRelic; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import java.io.File; @@ -18,8 +19,6 @@ public class OsVariablesInstance { public static final String TMP = "tmp"; public static final String SNAPSHOTS = "snapshots"; - public static final String LOG_FILE_PATH = "log_file_path"; - private static OsVariablesInstance instance; private final static Object lock = new Object(); @@ -28,26 +27,11 @@ public class OsVariablesInstance { private OsVariablesInstance() { osVariables = new OSVariables(); - /*Path k2root = Paths.get(AgentInfo.getInstance().getK2Home(), K_2_ROOT); - if (!k2root.toFile().isDirectory()) { - k2root.toFile().mkdir(); - } - - try { - Files.setPosixFilePermissions(k2root, PosixFilePermissions.fromString("rwxrwxrwx")); - } catch (Exception e) { - }*/ - -// osVariables.setK2RootDir(k2root.toString()); -// osVariables.setLogDirectory(Paths.get(k2root.toString(), LOGS, LANGUAGE_AGENT, AgentInfo.getInstance().getApplicationUUID()).toString()); - - if(NewRelic.getAgent().getConfig().getValue(LOG_FILE_PATH) != null) { - osVariables.setLogDirectory(Paths.get(NewRelic.getAgent().getConfig().getValue(LOG_FILE_PATH), IUtilConstants.NR_SECURITY_HOME, LOGS).toString()); - } else { + if(StringUtils.isNotBlank(AgentConfig.getInstance().getK2Home())) { osVariables.setLogDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), LOGS).toString()); + osVariables.setTmpDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), TMP, LANGUAGE_AGENT, AgentInfo.getInstance().getApplicationUUID()).toString()); } - osVariables.setTmpDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), TMP, LANGUAGE_AGENT, AgentInfo.getInstance().getApplicationUUID()).toString()); osVariables.setSnapshotDir(Paths.get(osVariables.getLogDirectory(), SNAPSHOTS).toString()); // osVariables.setPolicyConfigPath(Paths.get(k2root.toString(), CONFIG, LANGUAGE_AGENT).toString()); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/InstrumentationUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/InstrumentationUtils.java index 0cf9bb752..43da7f23d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/InstrumentationUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/InstrumentationUtils.java @@ -13,6 +13,7 @@ import com.newrelic.agent.security.intcodeagent.websocket.WSClient; import com.newrelic.agent.security.intcodeagent.websocket.WSReconnectionST; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; import java.io.File; import java.util.concurrent.TimeUnit; @@ -74,7 +75,9 @@ public static void shutdownLogic(boolean doResetInstrumentation) { ControlCommandProcessorThreadPool.shutDownPool(); EventSendPool.shutDownPool(); WSReconnectionST.shutDownPool(); - FileUtils.deleteQuietly(new File(OsVariablesInstance.getInstance().getOsVariables().getTmpDirectory())); + if(StringUtils.isNotBlank(OsVariablesInstance.getInstance().getOsVariables().getTmpDirectory())) { + FileUtils.deleteQuietly(new File(OsVariablesInstance.getInstance().getOsVariables().getTmpDirectory())); + } } catch (Throwable e) { logger.log(LogLevel.SEVERE, "Error while shutting down executor pools : ", e, diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java index 521f4cd75..3024d2b0e 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java @@ -1,12 +1,15 @@ package com.newrelic.agent.security.intcodeagent.filelogging; import com.newrelic.agent.security.AgentInfo; +import com.newrelic.agent.security.instrumentator.os.OSVariables; +import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.instrumentator.utils.AgentUtils; import com.newrelic.agent.security.intcodeagent.models.javaagent.LogMessage; import com.newrelic.agent.security.intcodeagent.properties.K2JALogProperties; import com.newrelic.agent.security.intcodeagent.websocket.EventSendPool; import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; import com.newrelic.api.agent.security.utils.logging.LogLevel; +import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.util.concurrent.*; @@ -26,6 +29,8 @@ public class FileLoggerThreadPool { protected boolean isLoggingToStdOut = false; + private static OSVariables osVariables = OsVariablesInstance.getInstance().getOsVariables(); + private FileLoggerThreadPool() throws IOException { // load the settings int queueSize = 15000; @@ -36,6 +41,19 @@ private FileLoggerThreadPool() throws IOException { maxfilesize = LogFileHelper.logFileLimit()*1024; TimeUnit timeUnit = TimeUnit.SECONDS; + try { + if(LogFileHelper.isLoggingToStdOut()){ + this.isLoggingToStdOut = true; + } + } catch (NumberFormatException e){} + + if(!isLoggingToStdOut && StringUtils.isNotBlank(osVariables.getLogDirectory())) { + isLoggingActive = false; + isInitLoggingActive = false; + return; + } + + boolean allowCoreThreadTimeOut = false; executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, timeUnit, @@ -62,11 +80,6 @@ public Thread newThread(Runnable r) { return t; } }); - try { - if(LogFileHelper.isLoggingToStdOut()){ - this.isLoggingToStdOut = true; - } - } catch (NumberFormatException e){} } @@ -122,14 +135,14 @@ public static FileLoggerThreadPool getInstance() { } public void log(LogLevel logLevel, String event, String logSourceClassName) { - if (logLevel.getLevel() == 1 || logLevel.getLevel() > LogWriter.defaultLogLevel) { + if (!isLoggingActive || logLevel.getLevel() == 1 || logLevel.getLevel() > LogWriter.defaultLogLevel) { return; } executor.submit(new LogWriter(logLevel, event, logSourceClassName, Thread.currentThread().getName())); } public void log(LogLevel logLevel, String event, Throwable throwableEvent, String logSourceClassName) { - if (logLevel.getLevel() == 1 || logLevel.getLevel() > LogWriter.defaultLogLevel) { + if (!isLoggingActive ||logLevel.getLevel() == 1 || logLevel.getLevel() > LogWriter.defaultLogLevel) { return; } executor.submit(new LogWriter(logLevel, event, throwableEvent, logSourceClassName, Thread.currentThread().getName())); @@ -137,7 +150,7 @@ public void log(LogLevel logLevel, String event, Throwable throwableEvent, Strin public void logInit(LogLevel logLevel, String event, String logSourceClassName) { postLogMessage(logLevel, event, null, logSourceClassName); - if (logLevel.getLevel() == 1 || logLevel.getLevel() > InitLogWriter.defaultLogLevel) { + if (!isInitLoggingActive || logLevel.getLevel() == 1 || logLevel.getLevel() > InitLogWriter.defaultLogLevel) { return; } if(!isLoggingToStdOut) { @@ -148,7 +161,7 @@ public void logInit(LogLevel logLevel, String event, String logSourceClassName) public void logInit(LogLevel logLevel, String event, Throwable throwableEvent, String logSourceClassName) { postLogMessage(logLevel, event, throwableEvent, logSourceClassName); - if (logLevel.getLevel() == 1 || logLevel.getLevel() > InitLogWriter.defaultLogLevel) { + if (!isInitLoggingActive || logLevel.getLevel() == 1 || logLevel.getLevel() > InitLogWriter.defaultLogLevel) { return; } if(!isLoggingToStdOut) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/FileCleaner.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/FileCleaner.java index 0bf88915f..beb314bf3 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/FileCleaner.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/FileCleaner.java @@ -8,6 +8,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.AgeFileFilter; import org.apache.commons.io.filefilter.DirectoryFileFilter; +import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.IOException; @@ -33,6 +34,9 @@ public class FileCleaner { public void run() { long delay = Instant.now().toEpochMilli() - TimeUnit.MINUTES.toMillis(2); logger.log(LogLevel.INFO, FILE_CLEANER_INVOKED_INITIATING_TEMP_FILE_DIRECTORY_CLEANUP, FileCleaner.class.getName()); + if(StringUtils.isBlank(osVariables.getTmpDirectory())) { + return; + } FileUtils.iterateFiles(new File(osVariables.getTmpDirectory()), new AgeFileFilter(delay), DirectoryFileFilter.INSTANCE).forEachRemaining( file -> { FileUtils.deleteQuietly(file); }); 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 8764c0b62..4dde2b4e7 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 @@ -27,6 +27,7 @@ public interface IUtilConstants { 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"; + String LOG_FILE_PATH = "log_file_path"; String NR_SECURITY_HOME = "nr-security-home"; String PROCESSED = "PROCESSED"; String ERROR = "ERROR"; From 462c795b3e84e95691823a503d692585c77144a8 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 5 Aug 2024 14:29:22 +0530 Subject: [PATCH 043/122] user ca_bundle_path from APM config send expected notice error in case of WSClient connection failure --- .../security/intcodeagent/websocket/WSClient.java | 12 +++++++++--- .../newrelic/agent/security/util/IUtilConstants.java | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) 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 64f1ffcfd..262534a8d 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 @@ -37,9 +37,7 @@ import java.security.cert.X509Certificate; import java.time.Instant; import java.time.ZoneId; -import java.util.Collection; -import java.util.LinkedList; -import java.util.Set; +import java.util.*; import java.util.concurrent.TimeUnit; public class WSClient extends WebSocketClient { @@ -70,6 +68,8 @@ public class WSClient extends WebSocketClient { private WebSocketImpl connection = null; + private Map noticeErrorCustomParameters = new HashMap<>(); + private SSLContext createSSLContext() throws Exception { KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); @@ -95,6 +95,7 @@ private SSLContext createSSLContext() throws Exception { logger.log(caCerts.size() > 0 ? LogLevel.INFO : LogLevel.SEVERE, String.format("Found %s certificates.", caCerts.size()), WSClient.class.getName()); + noticeErrorCustomParameters.put("ca_bundle_count", String.valueOf(caCerts.size())); // Initialize the keystore keystore.load(null, null); @@ -122,8 +123,10 @@ private InputStream getCaBundleStream() throws IOException { InputStream inputStream; String caBundlePath = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_CA_BUNDLE_PATH); if (StringUtils.isNotBlank(caBundlePath)) { + noticeErrorCustomParameters.put("ca_bundle_path", caBundlePath); inputStream = Files.newInputStream(Paths.get(caBundlePath)); } else { + noticeErrorCustomParameters.put("ca_bundle_path", "internal-pem"); inputStream = CommonUtils.getResourceStreamFromAgentJar("nr-custom-ca.pem"); } return inputStream; @@ -150,6 +153,7 @@ private WSClient() throws URISyntaxException { Proxy proxy = proxyManager(); if(proxy != null) { this.setProxy(proxy); + noticeErrorCustomParameters.put("proxy_host", proxy.address().toString()); } if (StringUtils.startsWithIgnoreCase(AgentConfig.getInstance().getConfig().getK2ServiceInfo().getValidatorServiceEndpointURL(), "wss:")) { try { @@ -159,6 +163,7 @@ private WSClient() throws URISyntaxException { logger.log(LogLevel.FINER, "Error creating socket factory", e, WSClient.class.getName()); } } + noticeErrorCustomParameters.put("csec_ws_url", AgentConfig.getInstance().getConfig().getK2ServiceInfo().getValidatorServiceEndpointURL()); logger.log(LogLevel.INFO, String.format("Connecting to WS client %s", AgentConfig.getInstance().getConfig().getK2ServiceInfo().getValidatorServiceEndpointURL()), WSClient.class.getName()); } @@ -289,6 +294,7 @@ public void onClose(int code, String reason, boolean remote) { @Override public void onError(Exception ex) { + NewRelic.noticeError(ex, noticeErrorCustomParameters, true); logger.logInit(LogLevel.SEVERE, String.format(IAgentConstants.WS_CONNECTION_UNSUCCESSFUL_INFO, AgentConfig .getInstance().getConfig().getK2ServiceInfo().getValidatorServiceEndpointURL(), ex.toString(), ex.getCause()), 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 8764c0b62..7ebccdf2c 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 @@ -24,7 +24,7 @@ public interface IUtilConstants { String NR_SECURITY_HOME_APP = "security.is_home_app"; - String NR_SECURITY_CA_BUNDLE_PATH = "security.ca_bundle_path"; + String NR_SECURITY_CA_BUNDLE_PATH = "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"; String NR_SECURITY_HOME = "nr-security-home"; From f70f7dc5c84cd45f9bbe164230cbf451d93a341d Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 5 Aug 2024 15:34:36 +0530 Subject: [PATCH 044/122] send expected error in case of connection closure also --- .../agent/security/intcodeagent/websocket/WSClient.java | 2 ++ 1 file changed, 2 insertions(+) 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 262534a8d..c05c31799 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 @@ -281,6 +281,8 @@ public void onMessage(String message) { public void onClose(int code, String reason, boolean remote) { logger.log(LogLevel.WARNING, CONNECTION_CLOSED_BY + (remote ? REMOTE_PEER : LOCAL) + CODE + code + REASON + reason, WSClient.class.getName()); + NewRelic.noticeError( CONNECTION_CLOSED_BY + (remote ? REMOTE_PEER : LOCAL) + CODE + code + + REASON + reason, noticeErrorCustomParameters, true); if (code == CloseFrame.NEVER_CONNECTED) { return; } From 3ab3d8a766144b91c3df984b5d4dcf9254aa0712 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 5 Aug 2024 16:09:42 +0530 Subject: [PATCH 045/122] Enable jedis-1.4.0 support --- settings.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/settings.gradle b/settings.gradle index ca13695b0..5cbeccc44 100644 --- a/settings.gradle +++ b/settings.gradle @@ -209,3 +209,4 @@ include 'instrumentation:weblogic-12.2' include 'instrumentation:jedis-4.0.0' include 'instrumentation:jedis-3.0.0' include 'instrumentation:jedis-2.7.1_2.7.2' +include 'instrumentation:jedis-1.4.0' \ No newline at end of file From d7691154c696dd459533bb04ace99fcca447d4d6 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 5 Aug 2024 19:05:58 +0530 Subject: [PATCH 046/122] fix message string --- .../agent/security/intcodeagent/websocket/WSClient.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 c05c31799..5a3ee4665 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 @@ -279,10 +279,10 @@ public void onMessage(String message) { @Override public void onClose(int code, String reason, boolean remote) { - logger.log(LogLevel.WARNING, CONNECTION_CLOSED_BY + (remote ? REMOTE_PEER : LOCAL) + CODE + code - + REASON + reason, WSClient.class.getName()); - NewRelic.noticeError( CONNECTION_CLOSED_BY + (remote ? REMOTE_PEER : LOCAL) + CODE + code - + REASON + reason, noticeErrorCustomParameters, true); + String message = CONNECTION_CLOSED_BY + (remote ? REMOTE_PEER : LOCAL) + CODE + code + + REASON + reason; + logger.log(LogLevel.WARNING, message, WSClient.class.getName()); + NewRelic.noticeError( message, true); if (code == CloseFrame.NEVER_CONNECTED) { return; } From 24537a6f03e078c4230e370a27159ae5d46fc35b Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 6 Aug 2024 17:19:00 +0530 Subject: [PATCH 047/122] fix log file creation, it should always instantiate after log and tmp directory setters --- .../java/com/newrelic/agent/security/AgentConfig.java | 6 ++---- .../security/intcodeagent/filelogging/InitLogWriter.java | 9 +-------- .../security/intcodeagent/filelogging/LogWriter.java | 9 +-------- 3 files changed, 4 insertions(+), 20 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 e26dc4a6c..612a4fe8a 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 @@ -60,12 +60,10 @@ public void instantiate(){ isNRSecurityEnabled = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_ENABLED, false); // Set required Group groupName = applyRequiredGroup(); - // Enable low severity hooks - // Set required LogLevel - logLevel = applyRequiredLogLevel(); - //Instantiation call please do not move or repeat this. osVariables = OsVariablesInstance.instantiate().getOsVariables(); + // Set required LogLevel + logLevel = applyRequiredLogLevel(); } private static final class InstanceHolder { 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 ba49ac376..11323663c 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 @@ -79,14 +79,7 @@ public class InitLogWriter implements Runnable { fileName = new File(osVariables.getLogDirectory(), "java-security-collector-init.log").getAbsolutePath(); currentLogFile = new File(fileName); currentLogFileName = fileName; - 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(); - } - + createLogFile(); } } 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 1fac40082..59f05e6e2 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 @@ -103,14 +103,7 @@ private static boolean createLogFile() { fileName = new File(osVariables.getLogDirectory(), "java-security-collector.log").getAbsolutePath(); currentLogFile = new File(fileName); currentLogFileName = fileName; - 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(); - } - + createLogFile(); } } From d68925d8cb88f2e696449feede4e66499ec69620 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 6 Aug 2024 17:47:20 +0530 Subject: [PATCH 048/122] assign NR_CSEC_HOME before directory creation --- .../src/main/java/com/newrelic/agent/security/AgentConfig.java | 2 +- 1 file changed, 1 insertion(+), 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 612a4fe8a..a741b741e 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 @@ -116,6 +116,7 @@ public boolean setK2HomePath(){ return false; } Path k2homePath = Paths.get(NR_CSEC_HOME, IUtilConstants.NR_SECURITY_HOME); + NR_CSEC_HOME = k2homePath.toString(); try { noticeErrorCustomParams.put("CSEC_HOME", k2homePath.toString()); if(!CommonUtils.forceMkdirs(k2homePath, DIRECTORY_PERMISSION)){ @@ -126,7 +127,6 @@ public boolean setK2HomePath(){ NewRelic.noticeError(e, noticeErrorCustomParams, true); 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())); AgentUtils.getInstance().getStatusLogValues().put("agent-location", NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION)); From 087d91d8e14514d07ece7e0c556c207aa6836736 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 7 Aug 2024 17:09:59 +0530 Subject: [PATCH 049/122] Update notice error msgs --- .../java/com/newrelic/agent/security/AgentConfig.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 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 a741b741e..7de6e768a 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 @@ -56,7 +56,9 @@ private AgentConfig(){ public void instantiate(){ //Set k2 home path boolean validHomePath = setK2HomePath(); - System.out.println("New Relic Security Agent: Setting csec home path to directory: "+NR_CSEC_HOME); + if(validHomePath) { + System.out.println("New Relic Security Agent: Setting csec home path to directory: " + NR_CSEC_HOME); + } isNRSecurityEnabled = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_ENABLED, false); // Set required Group groupName = applyRequiredGroup(); @@ -111,7 +113,7 @@ public boolean setK2HomePath(){ //system property `newrelic.home` or environment variable `NEWRELIC_HOME` NR_CSEC_HOME = NewRelic.getAgent().getConfig().getValue(AGENT_HOME); } else { - NewRelic.noticeError("CSEC home directory not found. Please check the agent configs or system property `newrelic.home` or environment variable `NEWRELIC_HOME`", noticeErrorCustomParams, true); + NewRelic.noticeError("CSEC home directory creation failed, reason directory not found. Please check the agent configs", noticeErrorCustomParams, true); System.err.println("[NR-CSEC-JA] CSEC home directory not found. Please check the agent configs or system property `newrelic.home` or environment variable `NEWRELIC_HOME`."); return false; } @@ -125,6 +127,7 @@ public boolean setK2HomePath(){ } } catch (IOException e) { NewRelic.noticeError(e, noticeErrorCustomParams, true); + NewRelic.noticeError(String.format("CSEC home directory creation failed, reason %s. Please check the agent configs", e.getMessage()), noticeErrorCustomParams, true); return false; } AgentUtils.getInstance().getStatusLogValues().put("csec-home", NR_CSEC_HOME); @@ -146,11 +149,11 @@ private boolean isValidK2HomePath(String k2Home) { return true; } noticeErrorCustomParams.put("CSEC_HOME_DISK_AVL_BYTES", String.valueOf(avail)); - NewRelic.noticeError("Insufficient disk space available to the location " + k2Home + " is : " + FileUtils.byteCountToDisplaySize(avail), noticeErrorCustomParams, true); + NewRelic.noticeError("CSEC home directory creation failed, reason : Insufficient disk space available to the location " + k2Home + " is : " + FileUtils.byteCountToDisplaySize(avail), noticeErrorCustomParams, true); System.err.println(String.format("[NR-CSEC-JA] Insufficient disk space available to the location %s is : %s", k2Home, FileUtils.byteCountToDisplaySize(avail))); return false; } - NewRelic.noticeError("CSEC home directory not found :"+k2Home, noticeErrorCustomParams, true); + NewRelic.noticeError("CSEC home directory creation failed, reason : CSEC home directory not found :"+k2Home, noticeErrorCustomParams, true); return false; } From 68ecd56ea81525b3777741845f1fba1b0d3353bd Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 8 Aug 2024 10:25:18 +0530 Subject: [PATCH 050/122] NR-262454: Fix for URISyntaxException --- .../javax-jndi/src/main/java/javax/naming/JNDIUtils.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/instrumentation-security/javax-jndi/src/main/java/javax/naming/JNDIUtils.java b/instrumentation-security/javax-jndi/src/main/java/javax/naming/JNDIUtils.java index b4c4576ce..5aa298c1a 100644 --- a/instrumentation-security/javax-jndi/src/main/java/javax/naming/JNDIUtils.java +++ b/instrumentation-security/javax-jndi/src/main/java/javax/naming/JNDIUtils.java @@ -8,6 +8,7 @@ import com.newrelic.api.agent.security.utils.logging.LogLevel; import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; @@ -35,7 +36,10 @@ public static AbstractOperation handleJNDIHook(String name, String methodName, S NewRelicSecurity.getAgent().registerOperation(operation); return operation; } - } catch (Exception ignored) { + } catch (URISyntaxException ignored) { + // Ignoring URISyntaxException + } + catch (Exception ignored) { NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, JAVAX_JNDI, ignored.getMessage()), ignored, JNDIUtils.class.getName()); NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, JAVAX_JNDI, ignored.getMessage()), ignored, JNDIUtils.class.getName()); } From 965fd359362d9b5a1de734a3087c844a7e7f1e77 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 8 Aug 2024 10:25:40 +0530 Subject: [PATCH 051/122] Restriction mode error handling Add capability to allow multiple test account IDs --- .../newrelic/agent/security/AgentConfig.java | 44 ++++++++++------- .../exceptions/RestrictionModeException.java | 20 ++++++++ .../utils/RestrictionUtility.java | 48 ++++++++++++------- .../agent/security/util/IUtilConstants.java | 2 +- .../security/schema/policy/AccountInfo.java | 21 +++++--- 5 files changed, 93 insertions(+), 42 deletions(-) create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/exceptions/RestrictionModeException.java 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 2fdec7789..bc8826697 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 @@ -1,17 +1,14 @@ package com.newrelic.agent.security; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.introspect.Annotated; -import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.newrelic.agent.security.instrumentator.os.OSVariables; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.instrumentator.utils.AgentUtils; +import com.newrelic.agent.security.intcodeagent.exceptions.RestrictionModeException; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.models.collectorconfig.AgentMode; import com.newrelic.agent.security.intcodeagent.utils.CronExpression; -import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; -import com.newrelic.api.agent.security.schema.annotations.JsonProperty; import com.newrelic.api.agent.security.schema.policy.*; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.filelogging.LogWriter; @@ -32,6 +29,7 @@ import java.text.ParseException; import java.time.Instant; import java.util.*; +import java.util.logging.Level; import static com.newrelic.agent.security.util.IUtilConstants.*; @@ -86,11 +84,17 @@ public long instantiate(){ } public long trigerIAST() { - if(agentMode.getIastScan().getEnabled() && agentMode.getIastScan().getRestricted()){ - long date = agentMode.getIastScan().getRestrictionCriteria().getScanTime().getNextScanTime().getTime(); - long currentTime = Instant.now().toEpochMilli(); - System.out.println("IAST is in restricted mode will start at "+date); - return date-currentTime; + try { + if(agentMode.getIastScan().getEnabled() && agentMode.getIastScan().getRestricted()){ + long date = agentMode.getIastScan().getRestrictionCriteria().getScanTime().getNextScanTime().getTime(); + long currentTime = Instant.now().toEpochMilli(); + return date-currentTime; + } + } catch (Exception e){ + //TODO send notice error + System.err.println("[NR-CSEC-JA] Error while calculating next scan time for IAST Restricted Mode. IAST Restricted Mode will be disabled."); + NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while calculating next scan time for IAST Restricted Mode. IAST Restricted Mode will be disabled."); + return Long.MAX_VALUE; } return 0; } @@ -105,7 +109,14 @@ private void instantiateAgentMode(String groupName) { readRaspConfig(); break; case IAST_RESTRICTED: - readIastRestrictedConfig(); + try { + readIastRestrictedConfig(); + } catch (RestrictionModeException e) { + System.err.println("[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled."); + NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled."); + //TODO Send Notice Error + this.agentMode.getIastScan().setEnabled(false); + } break; default: //this is default case which requires no changes @@ -114,25 +125,24 @@ private void instantiateAgentMode(String groupName) { } - private void readIastRestrictedConfig() { + private void readIastRestrictedConfig() throws RestrictionModeException { this.agentMode.getIastScan().setRestricted(true); RestrictionCriteria restrictionCriteria = this.agentMode.getIastScan().getRestrictionCriteria(); restrictionCriteria.setAccountInfo(new AccountInfo(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID))); - if(StringUtils.isBlank(restrictionCriteria.getAccountInfo().getAccountId())) { - //TODO raise error - + if(restrictionCriteria.getAccountInfo().isEmpty()) { + throw new RestrictionModeException("Account ID is required for IAST Restricted Mode"); } restrictionCriteria.getScanTime().setDuration(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SCAN_TIME_DURATION, 5)); - restrictionCriteria.getScanTime().setSchedule(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SCAN_TIME_SCHEDULE, "0 0 2 * * MON")); + restrictionCriteria.getScanTime().setSchedule(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SCAN_TIME_SCHEDULE, "0 0 0 * * ?")); if(CronExpression.isValidExpression(restrictionCriteria.getScanTime().getSchedule())){ try { restrictionCriteria.getScanTime().setNextScanTime(new CronExpression(restrictionCriteria.getScanTime().getSchedule()).getTimeAfter(new Date())); } catch (ParseException e) { - //TODO log error and set default scan time + throw new RestrictionModeException("Invalid cron expression provided for IAST Restricted Mode", e); } } else { - //TODO raise error + throw new RestrictionModeException("Invalid cron expression provided for IAST Restricted Mode"); } //Mapping parameters diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/exceptions/RestrictionModeException.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/exceptions/RestrictionModeException.java new file mode 100644 index 000000000..488c19da7 --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/exceptions/RestrictionModeException.java @@ -0,0 +1,20 @@ +package com.newrelic.agent.security.intcodeagent.exceptions; + +public class RestrictionModeException extends Exception { + + public RestrictionModeException() { + super(); + } + + public RestrictionModeException(String message) { + super(message); + } + + public RestrictionModeException(String message, Throwable cause) { + super(message, cause); + } + + public RestrictionModeException(Throwable cause) { + super(cause); + } +} \ No newline at end of file diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java index f674f602e..07b3a9609 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java @@ -4,11 +4,13 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; +import com.newrelic.agent.security.intcodeagent.exceptions.RestrictionModeException; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.HttpRequest; import com.newrelic.api.agent.security.schema.policy.MappingParameters; import com.newrelic.api.agent.security.schema.policy.RestrictionCriteria; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.w3c.dom.Document; @@ -39,7 +41,7 @@ public class RestrictionUtility { private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); public static boolean hasValidAccountId(RestrictionCriteria restrictionCriteria, HttpRequest request) { - String accountId = restrictionCriteria.getAccountInfo().getAccountId(); + List accountIds = restrictionCriteria.getAccountInfo().getAccountIds(); if (request == null) { return false; } @@ -51,18 +53,18 @@ public static boolean hasValidAccountId(RestrictionCriteria restrictionCriteria, switch (mappingParameter.getAccountIdLocation()) { case QUERY: List queryParameters = getQueryString(mappingParameter.getAccountIdKey(), request.getQueryParameters()); - match = matcher(accountId, queryParameters); + match = matcher(accountIds, queryParameters); break; case PATH: - match = matcher(accountId, request.getPathParameters()); + match = matcher(accountIds, request.getPathParameters()); break; case HEADER: List headerValues = getHeaderParameters(mappingParameter.getAccountIdKey(), request.getRequestHeaderParameters()); - match = matcher(accountId, headerValues); + match = matcher(accountIds, headerValues); break; case BODY: List bodyValues = getBodyParameters(mappingParameter.getAccountIdKey(), request.getRequestBodyParameters()); - match = matcher(accountId, bodyValues); + match = matcher(accountIds, bodyValues); break; } if(match){ @@ -96,12 +98,18 @@ private static List getQueryString(String accountId, Map values) { - if(values == null || values.isEmpty() || StringUtils.isBlank(accountId)) { - return false; + private static boolean matcher(List accountIds, List values) { + for (String accountId : accountIds) { + if(values == null || values.isEmpty() || StringUtils.isBlank(accountId)) { + continue; + } + String lowerCaseAccountId = accountId.toLowerCase(); + boolean contains = values.contains(lowerCaseAccountId); + if(contains){ + return true; + } } - String lowerCaseAccountId = accountId.toLowerCase(); - return values.contains(lowerCaseAccountId); + return false; } private static void parseHttpRequestParameters(HttpRequest request) { @@ -109,7 +117,11 @@ private static void parseHttpRequestParameters(HttpRequest request) { SEPARATOR_CHARS_QUESTION_MARK))); request.setQueryParameters(parseQueryParameters(request.getUrl())); request.setRequestHeaderParameters(parseRequestHeaders(request.getHeaders())); - request.setRequestBodyParameters(parseRequestBody(request.getBody(), request.getContentType(), request.getRequestBodyParameters())); + try { + request.setRequestBodyParameters(parseRequestBody(request.getBody(), request.getContentType(), request.getRequestBodyParameters())); + } catch (RestrictionModeException e) { + logger.log(LogLevel.WARNING, String.format("Request Body parsing failed reason %s", e.getMessage()), RestrictionUtility.class.getName()); + } request.setRequestBodyParameters(parseRequestParameterMap(request.getParameterMap(), request.getRequestBodyParameters())); request.setRequestParsed(true); } @@ -138,7 +150,7 @@ private static Map> parseRequestParameterMap(Map> parseRequestBody(StringBuilder body, String contentType, Map> requestBodyParameters) { + private static Map> parseRequestBody(StringBuilder body, String contentType, Map> requestBodyParameters) throws RestrictionModeException { if(StringUtils.isBlank(body.toString())) { return requestBodyParameters; } @@ -166,7 +178,7 @@ private static Map> parseRequestBody(StringBuilder body, St } - private static Map> parseXmlRequestBody(String body) { + private static Map> parseXmlRequestBody(String body) throws RestrictionModeException { //write logic to xml parsing Map> requestBodyParameters = new HashMap<>(); try { @@ -177,7 +189,8 @@ private static Map> parseXmlRequestBody(String bod Element root = document.getDocumentElement(); parseXmlNode(root, StringUtils.EMPTY, requestBodyParameters); } catch (Exception e) { - // TODO: log error + logger.log(LogLevel.FINER, String.format("JSON Request Body parsing failed for %s : reason %s", body, e.getMessage()), RestrictionUtility.class.getName()); + throw new RestrictionModeException(String.format("XML Request Body parsing failed : reason %s", e.getMessage()), e); } return requestBodyParameters; } @@ -200,7 +213,7 @@ private static void parseXmlNode(Node node, String baseKey, Map> parseJsonRequestBody(String body) { + private static Map> parseJsonRequestBody(String body) throws RestrictionModeException { JsonNode node; ObjectMapper mapper = new ObjectMapper(); try { @@ -208,10 +221,9 @@ private static Map> parseJsonRequestBody(String bo Map> requestBodyParameters = new HashMap<>(); return parseJsonNode(node, StringUtils.EMPTY, requestBodyParameters); } catch (JsonProcessingException e) { - //TODO log error + logger.log(LogLevel.FINER, String.format("JSON Request Body parsing failed for %s : reason %s", body, e.getMessage()), RestrictionUtility.class.getName()); + throw new RestrictionModeException(String.format("JSON Request Body parsing failed : reason %s", e.getMessage())+ e.getMessage(), e); } - return Collections.emptyMap(); - } private static Map> parseJsonNode(JsonNode node, String baseKey, Map> requestBodyParameters) { 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 bec8860eb..e32607c94 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 @@ -12,7 +12,7 @@ public interface IUtilConstants { String RESTRICTION_CRITERIA_SCAN_TIME_SCHEDULE = "security.restriction_criteria.scan_time.schedule"; String RESTRICTION_CRITERIA_SCAN_TIME_DURATION = "security.restriction_criteria.scan_time.duration"; String RESTRICTION_CRITERIA = "security.restriction_criteria"; - String RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID = "security.restriction_criteria.account_info.account_id"; + String RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID = "security.restriction_criteria.account_info.account_id_value"; String RESTRICTION_CRITERIA_MAPPING_PARAMETERS = "security.restriction_criteria.mapping_parameters"; String RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS = "security.restriction_criteria.skip_scan_parameters"; String RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_HEADER = "security.restriction_criteria.skip_scan_parameters.header"; diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/AccountInfo.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/AccountInfo.java index 0d0e679ab..5d79142b1 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/AccountInfo.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/AccountInfo.java @@ -1,18 +1,27 @@ package com.newrelic.api.agent.security.schema.policy; +import java.util.List; + public class AccountInfo { - private final String accountId; + private final List accountIds; public AccountInfo() { - this.accountId = null; + this.accountIds = null; + } + + public AccountInfo(List accountIds) { + this.accountIds = accountIds; } - public AccountInfo(String accountId) { - this.accountId = accountId; + public List getAccountIds() { + return accountIds; } - public String getAccountId() { - return accountId; + public boolean isEmpty() { + if(accountIds == null) { + return true; + } + return accountIds.isEmpty(); } } From c752ea957eed93eae54b1dd87555229fb2589443 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 8 Aug 2024 11:18:55 +0530 Subject: [PATCH 052/122] Add exception wrapper for notice errors --- .../newrelic/agent/security/AgentConfig.java | 9 +++++---- .../exceptions/SecurityNoticeError.java | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/exceptions/SecurityNoticeError.java 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 7de6e768a..650010452 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 @@ -3,6 +3,7 @@ import com.newrelic.agent.security.instrumentator.os.OSVariables; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.instrumentator.utils.AgentUtils; +import com.newrelic.agent.security.intcodeagent.exceptions.SecurityNoticeError; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.filelogging.LogWriter; @@ -113,7 +114,7 @@ public boolean setK2HomePath(){ //system property `newrelic.home` or environment variable `NEWRELIC_HOME` NR_CSEC_HOME = NewRelic.getAgent().getConfig().getValue(AGENT_HOME); } else { - NewRelic.noticeError("CSEC home directory creation failed, reason directory not found. Please check the agent configs", noticeErrorCustomParams, true); + NewRelic.noticeError(new SecurityNoticeError("CSEC home directory creation failed, reason directory not found. Please check the agent configs"), noticeErrorCustomParams, true); System.err.println("[NR-CSEC-JA] CSEC home directory not found. Please check the agent configs or system property `newrelic.home` or environment variable `NEWRELIC_HOME`."); return false; } @@ -122,12 +123,12 @@ public boolean setK2HomePath(){ try { noticeErrorCustomParams.put("CSEC_HOME", k2homePath.toString()); if(!CommonUtils.forceMkdirs(k2homePath, DIRECTORY_PERMISSION)){ - System.err.println(String.format("[NR-CSEC-JA] CSEC home directory creation failed at %s", NR_CSEC_HOME)); + NewRelic.noticeError(String.format("CSEC home directory creation failed, reason : %s", NR_CSEC_HOME), noticeErrorCustomParams, true); + System.err.printf("[NR-CSEC-JA] CSEC home directory creation failed at %s%n", NR_CSEC_HOME); return false; } } catch (IOException e) { - NewRelic.noticeError(e, noticeErrorCustomParams, true); - NewRelic.noticeError(String.format("CSEC home directory creation failed, reason %s. Please check the agent configs", e.getMessage()), noticeErrorCustomParams, true); + NewRelic.noticeError(new SecurityNoticeError(String.format("CSEC home directory creation failed, reason %s. Please check the agent configs", e.getMessage()), e), noticeErrorCustomParams, true); return false; } AgentUtils.getInstance().getStatusLogValues().put("csec-home", NR_CSEC_HOME); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/exceptions/SecurityNoticeError.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/exceptions/SecurityNoticeError.java new file mode 100644 index 000000000..40c9c5485 --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/exceptions/SecurityNoticeError.java @@ -0,0 +1,20 @@ +package com.newrelic.agent.security.intcodeagent.exceptions; + +public class SecurityNoticeError extends Exception { + + public SecurityNoticeError(){ + super(); + } + + public SecurityNoticeError(String message) { + super(message); + } + + public SecurityNoticeError(String message, Throwable cause) { + super(message, cause); + } + + public SecurityNoticeError(Throwable cause) { + super(cause); + } +} From b15a254c3619011738997a870b2cc4bc1147716e Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 8 Aug 2024 12:09:12 +0530 Subject: [PATCH 053/122] Add exception wrapper for notice errors --- .../agent/security/intcodeagent/websocket/WSClient.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 5a3ee4665..6e090400f 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 @@ -8,6 +8,7 @@ import com.newrelic.agent.security.instrumentator.utils.INRSettingsKey; import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessor; import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessorThreadPool; +import com.newrelic.agent.security.intcodeagent.exceptions.SecurityNoticeError; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; @@ -46,7 +47,7 @@ public class WSClient extends WebSocketClient { public static final String SENDING_EVENT = "sending event: "; public static final String UNABLE_TO_SEND_EVENT = "Unable to send event : "; public static final String ERROR_IN_WSOCK_CONNECTION = "Error in WSock connection : "; - public static final String CONNECTION_CLOSED_BY = "Connection closed by "; + public static final String CONNECTION_CLOSED_BY = "WS Connection closed by "; public static final String REMOTE_PEER = "remote peer."; public static final String LOCAL = "local."; public static final String CODE = " Code: "; @@ -282,7 +283,7 @@ public void onClose(int code, String reason, boolean remote) { String message = CONNECTION_CLOSED_BY + (remote ? REMOTE_PEER : LOCAL) + CODE + code + REASON + reason; logger.log(LogLevel.WARNING, message, WSClient.class.getName()); - NewRelic.noticeError( message, true); + NewRelic.noticeError(new SecurityNoticeError(message), noticeErrorCustomParameters, true); if (code == CloseFrame.NEVER_CONNECTED) { return; } @@ -296,7 +297,7 @@ public void onClose(int code, String reason, boolean remote) { @Override public void onError(Exception ex) { - NewRelic.noticeError(ex, noticeErrorCustomParameters, true); + NewRelic.noticeError(new SecurityNoticeError(CONNECTION_CLOSED_BY + ex.getClass().getSimpleName(), ex), noticeErrorCustomParameters, true); logger.logInit(LogLevel.SEVERE, String.format(IAgentConstants.WS_CONNECTION_UNSUCCESSFUL_INFO, AgentConfig .getInstance().getConfig().getK2ServiceInfo().getValidatorServiceEndpointURL(), ex.toString(), ex.getCause()), From 394d461b7e841eb596f41578d241c963475c65c5 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 8 Aug 2024 12:11:13 +0530 Subject: [PATCH 054/122] log unsupported agent under NR logs --- .../intcodeagent/controlcommand/ControlCommandProcessor.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java index f66a634d4..172fd166f 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java @@ -7,6 +7,7 @@ import com.newrelic.agent.security.instrumentator.utils.AgentUtils; import com.newrelic.agent.security.instrumentator.utils.InstrumentationUtils; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; +import com.newrelic.api.agent.NewRelic; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; import com.newrelic.agent.security.intcodeagent.models.config.AgentPolicyParameters; @@ -29,6 +30,7 @@ import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Map; +import java.util.logging.Level; public class ControlCommandProcessor implements Runnable { @@ -113,6 +115,7 @@ public void run() { logger.log(LogLevel.SEVERE, controlCommand.getArguments().get(0), ControlCommandProcessor.class.getSimpleName()); System.err.println(controlCommand.getArguments().get(0)); + NewRelic.getAgent().getLogger().log(Level.SEVERE, controlCommand.getArguments().get(0)); InstrumentationUtils.shutdownLogic(true); break; From 28463aeb368a860136dbce59f72a86f68e5644de Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 8 Aug 2024 12:19:09 +0530 Subject: [PATCH 055/122] Default proxy scheme requires setting of property jdk.http.auth.proxying.disabledSchemes --- .../newrelic/agent/security/intcodeagent/websocket/WSClient.java | 1 + 1 file changed, 1 insertion(+) 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 d9ca223a7..ae8a037bf 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 @@ -188,6 +188,7 @@ private static Proxy proxyManager() { */ // Requires System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); reference https://github.com/TooTallNate/Java-WebSocket/issues/1179#issuecomment-2184917604 System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); + System.setProperty("jdk.http.auth.proxying.disabledSchemes", ""); Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { From 8ddf7660232d72b42ee589c197a6a56b1188d54a Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 8 Aug 2024 12:51:35 +0530 Subject: [PATCH 056/122] set default values for config default schedule will be at 12 AM everyday --- .../newrelic/agent/security/AgentConfig.java | 19 ++++++++++--------- .../schema/policy/StrictMappings.java | 7 +++++++ 2 files changed, 17 insertions(+), 9 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 bc8826697..53c3f4587 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 @@ -39,6 +39,11 @@ public class AgentConfig { public static final String AGENT_JAR_LOCATION = "agent_jar_location"; public static final String AGENT_HOME = "agent_home"; + public static final String INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE = "Invalid cron expression provided for IAST Restricted Mode"; + public static final String ACCOUNT_ID_IS_REQUIRED_FOR_IAST_RESTRICTED_MODE = "Account ID is required for IAST Restricted Mode"; + public static final String ACCOUNT_ID_LOCATION = "account_id_location"; + public static final String ACCOUNT_ID_KEY = "account_id_key"; + public static final String ROUTE = "route"; private String NR_CSEC_HOME; private String logLevel; @@ -130,7 +135,7 @@ private void readIastRestrictedConfig() throws RestrictionModeException { RestrictionCriteria restrictionCriteria = this.agentMode.getIastScan().getRestrictionCriteria(); restrictionCriteria.setAccountInfo(new AccountInfo(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID))); if(restrictionCriteria.getAccountInfo().isEmpty()) { - throw new RestrictionModeException("Account ID is required for IAST Restricted Mode"); + throw new RestrictionModeException(ACCOUNT_ID_IS_REQUIRED_FOR_IAST_RESTRICTED_MODE); } restrictionCriteria.getScanTime().setDuration(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SCAN_TIME_DURATION, 5)); @@ -139,20 +144,16 @@ private void readIastRestrictedConfig() throws RestrictionModeException { try { restrictionCriteria.getScanTime().setNextScanTime(new CronExpression(restrictionCriteria.getScanTime().getSchedule()).getTimeAfter(new Date())); } catch (ParseException e) { - throw new RestrictionModeException("Invalid cron expression provided for IAST Restricted Mode", e); + throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE, e); } } else { - throw new RestrictionModeException("Invalid cron expression provided for IAST Restricted Mode"); + throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE); } //Mapping parameters List> mappingParameters = NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS, Collections.emptyList()); - ObjectMapper mapper = new ObjectMapper(); - mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() { - - }); for (Map mappingParameter : mappingParameters) { - MappingParameters matchingCriteria = new MappingParameters(HttpParameterLocation.valueOf(mappingParameter.get("account_id_location")), mappingParameter.get("account_id_key")); + MappingParameters matchingCriteria = new MappingParameters(HttpParameterLocation.valueOf(mappingParameter.get(ACCOUNT_ID_LOCATION)), mappingParameter.get(ACCOUNT_ID_KEY)); // MappingParameters matchingCriteria = mapper.convertValue(mappingParameter, MappingParameters.class); restrictionCriteria.getMappingParameters().add(matchingCriteria); } @@ -164,7 +165,7 @@ private void readIastRestrictedConfig() throws RestrictionModeException { //Strict Criteria List> strictCriteria = NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_STRICT, Collections.emptyList()); for (Map strictCriterion : strictCriteria) { - StrictMappings matchingCriteria = mapper.convertValue(strictCriterion, StrictMappings.class); + StrictMappings matchingCriteria = new StrictMappings(strictCriterion.get(ROUTE), HttpParameterLocation.valueOf(strictCriterion.get(ACCOUNT_ID_LOCATION)), strictCriterion.get(ACCOUNT_ID_KEY)); restrictionCriteria.getStrictMappings().add(matchingCriteria); } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/StrictMappings.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/StrictMappings.java index 8b26f1238..0ea0669e7 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/StrictMappings.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/StrictMappings.java @@ -15,6 +15,13 @@ public class StrictMappings { public StrictMappings() { } + public StrictMappings(String route, HttpParameterLocation accountIdLocation, String accountIdKey) { + this.route = route; + this.accountIdLocation = accountIdLocation; + this.accountIdKey = accountIdKey; + this.routePattern = Pattern.compile(route); + } + public String getRoute() { return route; } From 9630a81b5a85715bd72bf091ac6f628b11f2d060 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 8 Aug 2024 13:01:42 +0530 Subject: [PATCH 057/122] Renaming methods from K2 to Security --- .../newrelic/agent/security/AgentConfig.java | 31 +++++++++---------- .../os/OsVariablesInstance.java | 8 ++--- .../newrelic/api/agent/security/Agent.java | 6 ++-- 3 files changed, 20 insertions(+), 25 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 650010452..368b7b9aa 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 @@ -11,7 +11,6 @@ import com.newrelic.agent.security.intcodeagent.utils.CommonUtils; import com.newrelic.agent.security.util.IUtilConstants; import com.newrelic.api.agent.NewRelic; -import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import org.apache.commons.io.FileUtils; import org.apache.commons.io.comparator.LastModifiedFileComparator; import org.apache.commons.io.filefilter.FileFilterUtils; @@ -56,7 +55,7 @@ private AgentConfig(){ public void instantiate(){ //Set k2 home path - boolean validHomePath = setK2HomePath(); + boolean validHomePath = setSecurityHomePath(); if(validHomePath) { System.out.println("New Relic Security Agent: Setting csec home path to directory: " + NR_CSEC_HOME); } @@ -102,7 +101,7 @@ private String applyRequiredLogLevel() { return logLevel; } - public boolean setK2HomePath(){ + public boolean setSecurityHomePath(){ noticeErrorCustomParams.put(IUtilConstants.LOG_FILE_PATH, NewRelic.getAgent().getConfig().getValue(IUtilConstants.LOG_FILE_PATH)); noticeErrorCustomParams.put(AGENT_JAR_LOCATION, NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION)); noticeErrorCustomParams.put(AGENT_HOME, NewRelic.getAgent().getConfig().getValue(AGENT_HOME)); @@ -118,11 +117,11 @@ public boolean setK2HomePath(){ System.err.println("[NR-CSEC-JA] CSEC home directory not found. Please check the agent configs or system property `newrelic.home` or environment variable `NEWRELIC_HOME`."); return false; } - Path k2homePath = Paths.get(NR_CSEC_HOME, IUtilConstants.NR_SECURITY_HOME); - NR_CSEC_HOME = k2homePath.toString(); + Path SecurityhomePath = Paths.get(NR_CSEC_HOME, IUtilConstants.NR_SECURITY_HOME); + NR_CSEC_HOME = SecurityhomePath.toString(); try { - noticeErrorCustomParams.put("CSEC_HOME", k2homePath.toString()); - if(!CommonUtils.forceMkdirs(k2homePath, DIRECTORY_PERMISSION)){ + noticeErrorCustomParams.put("CSEC_HOME", SecurityhomePath.toString()); + if(!CommonUtils.forceMkdirs(SecurityhomePath, DIRECTORY_PERMISSION)){ NewRelic.noticeError(String.format("CSEC home directory creation failed, reason : %s", NR_CSEC_HOME), noticeErrorCustomParams, true); System.err.printf("[NR-CSEC-JA] CSEC home directory creation failed at %s%n", NR_CSEC_HOME); return false; @@ -132,16 +131,16 @@ public boolean setK2HomePath(){ return false; } 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("csec-home-permissions", String.valueOf(SecurityhomePath.toFile().canWrite() && SecurityhomePath.toFile().canRead())); AgentUtils.getInstance().getStatusLogValues().put("agent-location", NewRelic.getAgent().getConfig().getValue(AGENT_JAR_LOCATION)); - return isValidK2HomePath(NR_CSEC_HOME); + return isValidSecurityHomePath(NR_CSEC_HOME); } - private boolean isValidK2HomePath(String k2Home) { - if (StringUtils.isNotBlank(k2Home) && Paths.get(k2Home).toFile().isDirectory()) { + private boolean isValidSecurityHomePath(String securityHome) { + if (StringUtils.isNotBlank(securityHome) && Paths.get(securityHome).toFile().isDirectory()) { long avail = 0; try { - avail = Files.getFileStore(Paths.get(k2Home)).getUsableSpace(); + avail = Files.getFileStore(Paths.get(securityHome)).getUsableSpace(); } catch (Exception e) { return true; } @@ -150,11 +149,11 @@ private boolean isValidK2HomePath(String k2Home) { return true; } noticeErrorCustomParams.put("CSEC_HOME_DISK_AVL_BYTES", String.valueOf(avail)); - NewRelic.noticeError("CSEC home directory creation failed, reason : Insufficient disk space available to the location " + k2Home + " is : " + FileUtils.byteCountToDisplaySize(avail), noticeErrorCustomParams, true); - System.err.println(String.format("[NR-CSEC-JA] Insufficient disk space available to the location %s is : %s", k2Home, FileUtils.byteCountToDisplaySize(avail))); + NewRelic.noticeError("CSEC home directory creation failed, reason : Insufficient disk space available to the location " + securityHome + " is : " + FileUtils.byteCountToDisplaySize(avail), noticeErrorCustomParams, true); + System.err.println(String.format("[NR-CSEC-JA] Insufficient disk space available to the location %s is : %s", securityHome, FileUtils.byteCountToDisplaySize(avail))); return false; } - NewRelic.noticeError("CSEC home directory creation failed, reason : CSEC home directory not found :"+k2Home, noticeErrorCustomParams, true); + NewRelic.noticeError("CSEC home directory creation failed, reason : CSEC home directory not found :"+securityHome, noticeErrorCustomParams, true); return false; } @@ -214,7 +213,7 @@ public void setNRSecurityEnabled(boolean NRSecurityEnabled) { isNRSecurityEnabled = NRSecurityEnabled; } - public String getK2Home() { + public String getSecurityHome() { return NR_CSEC_HOME; } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java index b8448224e..1e8d5c30f 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java @@ -3,8 +3,6 @@ import com.newrelic.agent.security.AgentConfig; import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; -import com.newrelic.agent.security.util.IUtilConstants; -import com.newrelic.api.agent.NewRelic; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; @@ -28,9 +26,9 @@ public class OsVariablesInstance { private OsVariablesInstance() { osVariables = new OSVariables(); - if(StringUtils.isNotBlank(AgentConfig.getInstance().getK2Home())) { - osVariables.setLogDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), LOGS).toString()); - osVariables.setTmpDirectory(Paths.get(AgentConfig.getInstance().getK2Home(), TMP, LANGUAGE_AGENT, AgentInfo.getInstance().getApplicationUUID()).toString()); + if(StringUtils.isNotBlank(AgentConfig.getInstance().getSecurityHome())) { + osVariables.setLogDirectory(Paths.get(AgentConfig.getInstance().getSecurityHome(), LOGS).toString()); + osVariables.setTmpDirectory(Paths.get(AgentConfig.getInstance().getSecurityHome(), TMP, LANGUAGE_AGENT, AgentInfo.getInstance().getApplicationUUID()).toString()); } osVariables.setSnapshotDir(Paths.get(osVariables.getLogDirectory(), SNAPSHOTS).toString()); // osVariables.setPolicyConfigPath(Paths.get(k2root.toString(), CONFIG, LANGUAGE_AGENT).toString()); 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 ab468d430..70d762cc0 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 @@ -29,8 +29,6 @@ import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -143,7 +141,7 @@ private void initialise() { setInitialised(true); populateLinkingMetadata(); populateApplicationTmpDir(); - startK2Services(); + startSecurityServices(); info.agentStatTrigger(true); } @@ -174,7 +172,7 @@ private void populateLinkingMetadata() { info.setLinkingMetadata(linkingMetaData); } - private void startK2Services() { + private void startSecurityServices() { HealthCheckScheduleThread.getInstance().scheduleNewTask(); FileCleaner.scheduleNewTask(); SchedulerHelper.getInstance().scheduleLowSeverityFilterCleanup(LowSeverityHelper::clearLowSeverityEventFilter, From 79bb67167756824012aeea9bfd4dea5ed9a7ce23 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 8 Aug 2024 15:52:50 +0530 Subject: [PATCH 058/122] Send notice error on failure of IAST restriction config --- .../com/newrelic/agent/security/AgentConfig.java | 13 +++++++++++-- .../java/com/newrelic/api/agent/security/Agent.java | 7 +++++++ .../api/agent/security/schema/policy/RASPScan.java | 2 +- 3 files changed, 19 insertions(+), 3 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 53c3f4587..57faaa6d8 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 @@ -9,6 +9,7 @@ import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.models.collectorconfig.AgentMode; import com.newrelic.agent.security.intcodeagent.utils.CronExpression; +import com.newrelic.api.agent.security.Agent; import com.newrelic.api.agent.security.schema.policy.*; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.filelogging.LogWriter; @@ -76,6 +77,7 @@ public long instantiate(){ isNRSecurityEnabled = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_ENABLED, false); // Set required Group groupName = applyRequiredGroup(); + Agent.getCustomNoticeErrorParameters().put(IUtilConstants.SECURITY_MODE, groupName); // Enable low severity hooks // Set required LogLevel logLevel = applyRequiredLogLevel(); @@ -108,7 +110,7 @@ private void instantiateAgentMode(String groupName) { this.agentMode = new AgentMode(groupName); switch (groupName){ case IAST: - //this is default case which requires no changes + readIastConfig(); break; case RASP: readRaspConfig(); @@ -119,7 +121,7 @@ private void instantiateAgentMode(String groupName) { } catch (RestrictionModeException e) { System.err.println("[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled."); NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled."); - //TODO Send Notice Error + NewRelic.noticeError(e, Agent.getCustomNoticeErrorParameters(), true); this.agentMode.getIastScan().setEnabled(false); } break; @@ -130,8 +132,14 @@ private void instantiateAgentMode(String groupName) { } + private void readIastConfig() { + this.agentMode.getIastScan().setEnabled(true); + this.agentMode.getRaspScan().setEnabled(false); + } + private void readIastRestrictedConfig() throws RestrictionModeException { this.agentMode.getIastScan().setRestricted(true); + Agent.getCustomNoticeErrorParameters().put(IAST_RESTRICTED, String.valueOf(true)); RestrictionCriteria restrictionCriteria = this.agentMode.getIastScan().getRestrictionCriteria(); restrictionCriteria.setAccountInfo(new AccountInfo(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID))); if(restrictionCriteria.getAccountInfo().isEmpty()) { @@ -226,6 +234,7 @@ public boolean setK2HomePath() throws IOException { return false; } NR_CSEC_HOME = k2homePath.toString(); + Agent.getCustomNoticeErrorParameters().put(IUtilConstants.NR_SECURITY_HOME, NR_CSEC_HOME); 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", agentJarLocation); 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 3f1d40827..3f729a4f7 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 @@ -43,6 +43,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; @@ -70,6 +71,8 @@ public class Agent implements SecurityAgent { private java.net.URL agentJarURL; private Instrumentation instrumentation; + private static final Map customNoticeErrorParameters = new ConcurrentHashMap<>(); + private static final class InstanceHolder { static final Agent instance = new Agent(); } @@ -91,6 +94,10 @@ private Agent(){ System.setProperty("org.slf4j.simpleLogger.logFile", "System.out"); } + public static Map getCustomNoticeErrorParameters() { + return customNoticeErrorParameters; + } + private void initialise() { if (!isInitialised()) { diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RASPScan.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RASPScan.java index d1d1e0f25..91c5cc09f 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RASPScan.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RASPScan.java @@ -2,7 +2,7 @@ public class RASPScan { - private Boolean enabled = true; + private Boolean enabled = false; public RASPScan() { } From b36154c1ce13e3ad60c4fee65201eaf41ef1f053 Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Fri, 9 Aug 2024 09:55:19 +0530 Subject: [PATCH 059/122] [NR-283915] Route detection support for mule server (#293) * Route detection Support for mule server --- .../instrumentation/mule36/MuleHelper.java | 19 ++++++++++++++++++- ...ttpRequestToMuleEvent_Instrumentation.java | 10 ++++++++-- .../async/RequestHandler_Instrumentation.java | 10 ++++++++-- .../instrumentation/mule37/MuleHelper.java | 19 ++++++++++++++++++- ...ttpRequestToMuleEvent_Instrumentation.java | 10 ++++++++-- .../async/RequestHandler_Instrumentation.java | 11 +++++++++-- 6 files changed, 69 insertions(+), 10 deletions(-) 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 3a79f35d7..dd226db05 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 @@ -7,7 +7,9 @@ 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.Framework; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import org.mule.api.processor.MessageProcessor; import org.mule.module.http.api.HttpHeaders; import org.mule.module.http.api.listener.HttpListener; @@ -29,6 +31,7 @@ public class MuleHelper { private static final String EMPTY = ""; public static final String LIBRARY_NAME = "MULE-SERVER"; private static final Map handlerMap = new HashMap<>(); + public static final String MULE_3_6 = "MULE-3.6"; public static void processHttpRequestHeader(HttpRequest httpRequest, com.newrelic.api.agent.security.schema.HttpRequest securityRequest @@ -114,10 +117,24 @@ public static void gatherURLMappings(HttpListener messageSource, List getHandlerMap() { return handlerMap; } + + // route detection + public static void setRequestRoute(String listenerPath) { + if (NewRelicSecurity.isHookProcessingActive()) { + try { + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(listenerPath); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.MULE); + } catch (Exception e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, MULE_3_6, e.getMessage()), e, MuleHelper.class.getName()); + } + } + } } diff --git a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java index ca9faf1b5..d5c2ac80c 100644 --- a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java +++ b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java @@ -9,6 +9,7 @@ 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.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -24,6 +25,7 @@ public static MuleEvent transform(final HttpRequestContext requestContext, final { boolean isLockAcquired = acquireLockIfPossible(requestContext.hashCode()); MuleEvent event; + MuleHelper.setRequestRoute(listenerPath); if (isLockAcquired) { preprocessSecurityHook(requestContext); } @@ -82,7 +84,9 @@ private static void preprocessSecurityHook(HttpRequestContext requestContext) { // TODO: need to update UserClassEntity ServletHelper.registerUserLevelCode(MuleHelper.LIBRARY_NAME); securityRequest.setRequestParsed(true); - } catch (Throwable ignored){} + } catch (Throwable ignored){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, MuleHelper.MULE_3_6, ignored.getMessage()), ignored, HttpRequestToMuleEvent_Instrumentation.class.getName()); + } } private static void postProcessSecurityHook() { @@ -107,9 +111,11 @@ private static void postProcessSecurityHook() { 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, MuleHelper.MULE_3_6, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); throw e; } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_3_6, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_3_6, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); } } diff --git a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java index 3ebd77e15..da85e3095 100644 --- a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java +++ b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java @@ -9,11 +9,13 @@ 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.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 org.mule.module.http.internal.domain.request.HttpRequest; import org.mule.module.http.internal.domain.request.HttpRequestContext; +import org.mule.module.http.internal.listener.HttpRequestToMuleEvent_Instrumentation; @Weave(type = MatchType.Interface, originalName = "org.mule.module.http.internal.listener.async.RequestHandler") public class RequestHandler_Instrumentation { @@ -76,7 +78,9 @@ private void preprocessSecurityHook(HttpRequestContext requestContext) { // TODO: need to update UserClassEntity ServletHelper.registerUserLevelCode(MuleHelper.LIBRARY_NAME); securityRequest.setRequestParsed(true); - } catch (Throwable ignored){} + } catch (Throwable ignored){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, MuleHelper.MULE_3_6, ignored.getMessage()), ignored, HttpRequestToMuleEvent_Instrumentation.class.getName()); + } } private void postProcessSecurityHook() { @@ -101,9 +105,11 @@ private void postProcessSecurityHook() { 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, MuleHelper.MULE_3_6, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); throw e; } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_3_6, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_3_6, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.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 afc9c97ba..a1b00a487 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 @@ -7,11 +7,14 @@ 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.Framework; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; +import com.newrelic.api.agent.security.utils.logging.LogLevel; 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.module.http.internal.listener.ListenerPath; import org.mule.processor.InvokerMessageProcessor; import java.util.HashMap; @@ -28,6 +31,7 @@ public class MuleHelper { private static final String EMPTY = ""; public static final String LIBRARY_NAME = "MULE-SERVER"; private static final Map handlerMap = new HashMap<>(); + public static final String MULE_3_7 = "MULE-3.7"; public static void processHttpRequestHeader(HttpRequest httpRequest, com.newrelic.api.agent.security.schema.HttpRequest securityRequest) { for (String headerName : httpRequest.getHeaderNames()) { @@ -108,10 +112,23 @@ public static void gatherURLMappings(HttpListener messageSource, List getHandlerMap() { return handlerMap; } + + public static void setRequestRoute(ListenerPath listenerPath) { + if (NewRelicSecurity.isHookProcessingActive()) { + try { + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(listenerPath.getResolvedPath()); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.MULE); + } catch (Exception e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, MULE_3_7, e.getMessage()), e, MuleHelper.class.getName()); + } + } + } } diff --git a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java index 521808b1a..62c6c4175 100644 --- a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java +++ b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java @@ -9,6 +9,7 @@ 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.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -24,6 +25,7 @@ public static MuleEvent transform(final HttpRequestContext requestContext, final { boolean isLockAcquired = acquireLockIfPossible(requestContext.hashCode()); MuleEvent event; + MuleHelper.setRequestRoute(listenerPath); if (isLockAcquired) { preprocessSecurityHook(requestContext); } @@ -82,7 +84,9 @@ private static void preprocessSecurityHook(HttpRequestContext requestContext) { // TODO: need to update UserClassEntity ServletHelper.registerUserLevelCode(MuleHelper.LIBRARY_NAME); securityRequest.setRequestParsed(true); - } catch (Throwable ignored){} + } catch (Throwable ignored){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, MuleHelper.MULE_3_7, ignored.getMessage()), ignored, HttpRequestToMuleEvent_Instrumentation.class.getName()); + } } private static void postProcessSecurityHook() { @@ -107,9 +111,11 @@ private static void postProcessSecurityHook() { 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, MuleHelper.MULE_3_7, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); throw e; } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_3_7, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_3_7, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); } } diff --git a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java index 0d1c0d15f..4a9f526ac 100644 --- a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java +++ b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java @@ -9,14 +9,17 @@ 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.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 org.mule.module.http.internal.domain.request.HttpRequest; import org.mule.module.http.internal.domain.request.HttpRequestContext; +import org.mule.module.http.internal.listener.HttpRequestToMuleEvent_Instrumentation; @Weave(type = MatchType.Interface, originalName = "org.mule.module.http.internal.listener.async.RequestHandler") public class RequestHandler_Instrumentation { + public void handleRequest(HttpRequestContext requestContext, HttpResponseReadyCallback responseCallback) { boolean isLockAcquired = acquireLockIfPossible(requestContext.hashCode()); if (isLockAcquired) { @@ -76,7 +79,9 @@ private void preprocessSecurityHook(HttpRequestContext requestContext) { // TODO: need to update UserClassEntity ServletHelper.registerUserLevelCode(MuleHelper.LIBRARY_NAME); securityRequest.setRequestParsed(true); - } catch (Throwable ignored){} + } catch (Throwable ignored){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, MuleHelper.MULE_3_7, ignored.getMessage()), ignored, HttpRequestToMuleEvent_Instrumentation.class.getName()); + } } private void postProcessSecurityHook() { @@ -101,9 +106,11 @@ private void postProcessSecurityHook() { 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, MuleHelper.MULE_3_7, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); throw e; } + NewRelicSecurity.getAgent().log(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_3_7, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); + NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE , String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, MuleHelper.MULE_3_7, e.getMessage()), e, HttpRequestToMuleEvent_Instrumentation.class.getName()); } } From 5181eb8130819c0ec1c68e501bba24729c324a81 Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Fri, 9 Aug 2024 09:56:04 +0530 Subject: [PATCH 060/122] NR-288606: Fix for bug NR-250981 where false API reported for CXF framework (#301) --- .../instrumentation/helpers/URLMappingsHelper.java | 8 ++++++++ 1 file changed, 8 insertions(+) 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 037fb4fab..50529294c 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 @@ -27,6 +27,14 @@ public class URLMappingsHelper { add("org.apache.catalina.servlets.DefaultServlet"); add("org.eclipse.jetty.servlet.DefaultServlet"); add("grails.plugin.databasemigration.DbdocController"); + add("org.apache.cxf.transport.servlet.CXFServlet"); + add("javax.faces.webapp.FacesServlet"); + add("jakarta.faces.webapp.FacesServlet"); + add("weblogic.servlet.JSPServlet"); + add("weblogic.servlet.FileServlet"); + add("weblogic.management.rest.JerseyServlet"); + add("com.caucho.jsp.XtpServlet"); + add("com.caucho.jsp.JspServlet"); }}; public static Set getApplicationURLMappings() { From ec05babb4f24cf5c8d9f6940f020d40620908045 Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Fri, 9 Aug 2024 09:57:17 +0530 Subject: [PATCH 061/122] [NR-265915] API Endpoint Phase 2 : Detect route of an endpoint for Play Framework (#284) * Route Detection Support for Play Framework * Add Unit Tests for play route detection support --- .../play2_13/HandlerInvoker.scala | 11 ++++ .../play2_7/APIEndpointTest.java | 51 +++++++++++++++--- .../src/test/resources/conf/routes | 3 +- .../play24/HandlerInvoker.scala | 13 ++++- .../play26/HandlerInvoker.scala | 11 ++++ .../play26/APIEndpointTest.java | 52 ++++++++++++++++--- .../play-2.6/src/test/resources/conf/routes | 3 +- 7 files changed, 127 insertions(+), 17 deletions(-) diff --git a/instrumentation-security/play-2.13_2.7/src/main/scala/com/newrelic/agent/security/instrumentation/play2_13/HandlerInvoker.scala b/instrumentation-security/play-2.13_2.7/src/main/scala/com/newrelic/agent/security/instrumentation/play2_13/HandlerInvoker.scala index e87915497..efc73744b 100644 --- a/instrumentation-security/play-2.13_2.7/src/main/scala/com/newrelic/agent/security/instrumentation/play2_13/HandlerInvoker.scala +++ b/instrumentation-security/play-2.13_2.7/src/main/scala/com/newrelic/agent/security/instrumentation/play2_13/HandlerInvoker.scala @@ -9,6 +9,7 @@ package com.newrelic.agent.security.instrumentation.play2_13 import com.newrelic.api.agent.security.NewRelicSecurity import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper +import com.newrelic.api.agent.security.schema.Framework import com.newrelic.api.agent.security.utils.logging.LogLevel import com.newrelic.api.agent.weaver.{MatchType, Weave, Weaver} import play.api.mvc.Handler @@ -35,6 +36,16 @@ class NewRelicWrapperInvoker[A](underlyingInvoker: HandlerInvoker[A], handlerDef } catch { case t: Throwable => NewRelicSecurity.getAgent.log(LogLevel.FINEST, String.format(GenericHelper.ERROR_WHILE_DETECTING_USER_CLASS, "PLAY-2.13_2.7"), t, this.getClass.getName) } + + // route detection + try { + if (NewRelicSecurity.isHookProcessingActive) { + NewRelicSecurity.getAgent.getSecurityMetaData.getRequest.setRoute(handlerDef.path) + NewRelicSecurity.getAgent.getSecurityMetaData.getMetaData.setFramework(Framework.PLAY) + } + } catch { + case t: Throwable => NewRelicSecurity.getAgent.log(LogLevel.FINEST, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, "PLAY-2.13_2.7"), t, this.getClass.getName) + } underlyingInvoker.call(call) } } 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 index ddf7bd9fd..6cf9dfd65 100644 --- 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 @@ -13,6 +13,7 @@ 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.schema.Framework; import com.newrelic.api.agent.security.schema.SecurityMetaData; import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; @@ -43,16 +44,15 @@ public class APIEndpointTest { 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("/post/$data<[^/]+>", SimpleJavaController.class.getName() + ".post(data:String)"); + expectedMappings.put("/post1/$data<[a-zA-Z]+>", 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()); + makeRequest("/hello"); Set actualMappings = URLMappingsHelper.getApplicationURLMappings(); Assert.assertNotNull(actualMappings); @@ -64,15 +64,52 @@ public void testControllerActions() throws IOException { // verification of user-class entity SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); SecurityMetaData metaData = introspector.getSecurityMetaData(); + verifyUserClassDetection(metaData, "hello"); + + // verification of route detection + Assert.assertEquals("/hello", metaData.getRequest().getRoute()); + Assert.assertEquals(Framework.PLAY.name(), metaData.getMetaData().getFramework()); + } + + @Test + public void testRouteDetection() throws IOException { + makeRequest("/post/data"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + SecurityMetaData metaData = introspector.getSecurityMetaData(); + + verifyUserClassDetection(metaData, "post"); + Assert.assertEquals("/post/$data<[^/]+>", metaData.getRequest().getRoute()); + Assert.assertEquals(Framework.PLAY.name(), metaData.getMetaData().getFramework()); + } + + @Test + public void testRouteDetection1() throws IOException { + makeRequest("/post1/data"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + SecurityMetaData metaData = introspector.getSecurityMetaData(); + + verifyUserClassDetection(metaData, "post"); + Assert.assertEquals("/post1/$data<[a-zA-Z]+>", metaData.getRequest().getRoute()); + Assert.assertEquals(Framework.PLAY.name(), metaData.getMetaData().getFramework()); + } + + private void makeRequest(String path) throws IOException { + HttpURLConnection conn = ((HttpURLConnection) serverRule.getEndpoint(path).openConnection()); + conn.connect(); + System.out.println(conn.getResponseCode()); + } + + private void verifyUserClassDetection(SecurityMetaData metaData, String methodName) { Assert.assertNotNull(metaData.getMetaData()); Assert.assertTrue(metaData.getMetaData().isUserLevelServiceMethodEncountered()); StackTraceElement element = metaData.getCustomAttribute(GenericHelper.USER_CLASS_ENTITY, StackTraceElement.class); Assert.assertNotNull(element); Assert.assertEquals(SimpleJavaController.class.getName(), element.getClassName()); - Assert.assertEquals("hello", element.getMethodName()); + Assert.assertEquals(methodName, element.getMethodName()); } - private void assertMappings(ApplicationURLMapping actualMapping){ Assert.assertNotNull(actualMapping.getPath()); Assert.assertNotNull(actualMapping.getHandler()); @@ -80,7 +117,7 @@ private void assertMappings(ApplicationURLMapping actualMapping){ String path = actualMapping.getPath(); String handler = expectedMappings.get(path); - String method = !path.equals("/post") ? "GET" : "POST"; + String method = "GET"; Assert.assertEquals(handler, actualMapping.getHandler()); Assert.assertEquals(method, actualMapping.getMethod()); 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 index 530d9c58d..3f2a31c82 100644 --- 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 @@ -2,4 +2,5 @@ GET /hello com.nr.agent.security.instrumentation.play2_7.SimpleJava 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 +GET /post/:data com.nr.agent.security.instrumentation.play2_7.SimpleJavaController.post(data: String) +GET /post1/$data<[a-zA-Z]+> com.nr.agent.security.instrumentation.play2_7.SimpleJavaController.post(data: String) \ No newline at end of file diff --git a/instrumentation-security/play-2.4/src/main/scala/com/newrelic/agent/security/instrumentation/play24/HandlerInvoker.scala b/instrumentation-security/play-2.4/src/main/scala/com/newrelic/agent/security/instrumentation/play24/HandlerInvoker.scala index cb0d75e35..ced6c8e13 100644 --- a/instrumentation-security/play-2.4/src/main/scala/com/newrelic/agent/security/instrumentation/play24/HandlerInvoker.scala +++ b/instrumentation-security/play-2.4/src/main/scala/com/newrelic/agent/security/instrumentation/play24/HandlerInvoker.scala @@ -8,7 +8,8 @@ package com.newrelic.agent.security.instrumentation.play24 import com.newrelic.api.agent.security.NewRelicSecurity -import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper +import com.newrelic.api.agent.security.instrumentation.helpers.{GenericHelper, URLMappingsHelper} +import com.newrelic.api.agent.security.schema.{Framework, SecurityMetaData} import com.newrelic.api.agent.security.utils.logging.LogLevel import com.newrelic.api.agent.weaver.{MatchType, Weave, Weaver} import play.api.mvc.Handler @@ -34,6 +35,16 @@ class NewRelicWrapperInvoker[A](underlyingInvoker: HandlerInvoker[A], handlerDef } catch { case t: Throwable => NewRelicSecurity.getAgent.log(LogLevel.FINEST, String.format(GenericHelper.ERROR_WHILE_DETECTING_USER_CLASS, "PLAY-2.4"), t, this.getClass.getName) } + + // route detection + try { + if (NewRelicSecurity.isHookProcessingActive) { + NewRelicSecurity.getAgent.getSecurityMetaData.getRequest.setRoute(handlerDef.path) + NewRelicSecurity.getAgent.getSecurityMetaData.getMetaData.setFramework(Framework.PLAY) + } + } catch { + case t: Throwable => NewRelicSecurity.getAgent.log(LogLevel.FINEST, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, "PLAY-2.4"), t, this.getClass.getName) + } underlyingInvoker.call(call) } } diff --git a/instrumentation-security/play-2.6/src/main/scala/com/newrelic/agent/security/instrumentation/play26/HandlerInvoker.scala b/instrumentation-security/play-2.6/src/main/scala/com/newrelic/agent/security/instrumentation/play26/HandlerInvoker.scala index 389c30bf9..ca6b4fbf8 100644 --- a/instrumentation-security/play-2.6/src/main/scala/com/newrelic/agent/security/instrumentation/play26/HandlerInvoker.scala +++ b/instrumentation-security/play-2.6/src/main/scala/com/newrelic/agent/security/instrumentation/play26/HandlerInvoker.scala @@ -9,6 +9,7 @@ package com.newrelic.agent.security.instrumentation.play26 import com.newrelic.api.agent.security.NewRelicSecurity import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper +import com.newrelic.api.agent.security.schema.Framework import com.newrelic.api.agent.security.utils.logging.LogLevel import com.newrelic.api.agent.weaver.{MatchType, Weave, Weaver} import play.api.mvc.Handler @@ -35,6 +36,16 @@ class NewRelicWrapperInvoker[A](underlyingInvoker: HandlerInvoker[A], handlerDef } catch { case t: Throwable => NewRelicSecurity.getAgent.log(LogLevel.FINEST, String.format(GenericHelper.ERROR_WHILE_DETECTING_USER_CLASS, "PLAY-2.6"), t, this.getClass.getName) } + + // route detection + try { + if (NewRelicSecurity.isHookProcessingActive) { + NewRelicSecurity.getAgent.getSecurityMetaData.getRequest.setRoute(handlerDef.path) + NewRelicSecurity.getAgent.getSecurityMetaData.getMetaData.setFramework(Framework.PLAY) + } + } catch { + case t: Throwable => NewRelicSecurity.getAgent.log(LogLevel.FINEST, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, "PLAY-2.6"), t, this.getClass.getName) + } underlyingInvoker.call(call) } } 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 index 04b364d3a..cd02ecc49 100644 --- 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 @@ -14,6 +14,7 @@ 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.schema.Framework; import com.newrelic.api.agent.security.schema.SecurityMetaData; import com.newrelic.security.test.marker.Java17IncompatibleTest; import org.junit.Assert; @@ -23,6 +24,7 @@ import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; +import java.awt.*; import java.io.IOException; import java.net.HttpURLConnection; import java.util.HashMap; @@ -44,16 +46,15 @@ public class APIEndpointTest { 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("/post/$data<[^/]+>", SimpleJavaController.class.getName() + ".post(data:String)"); + expectedMappings.put("/post1/$data<[a-zA-Z]+>", 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()); + makeRequest("/hello"); Set actualMappings = URLMappingsHelper.getApplicationURLMappings(); Assert.assertNotNull(actualMappings); @@ -65,15 +66,52 @@ public void testControllerActions() throws IOException { // verification of user-class entity SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); SecurityMetaData metaData = introspector.getSecurityMetaData(); + verifyUserClassDetection(metaData, "hello"); + + // verification of route detection + Assert.assertEquals("/hello", metaData.getRequest().getRoute()); + Assert.assertEquals(Framework.PLAY.name(), metaData.getMetaData().getFramework()); + } + + @Test + public void testRouteDetection() throws IOException { + makeRequest("/post/data"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + SecurityMetaData metaData = introspector.getSecurityMetaData(); + + verifyUserClassDetection(metaData, "post"); + Assert.assertEquals("/post/$data<[^/]+>", metaData.getRequest().getRoute()); + Assert.assertEquals(Framework.PLAY.name(), metaData.getMetaData().getFramework()); + } + + @Test + public void testRouteDetection1() throws IOException { + makeRequest("/post1/data"); + + SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector(); + SecurityMetaData metaData = introspector.getSecurityMetaData(); + + verifyUserClassDetection(metaData, "post"); + Assert.assertEquals("/post1/$data<[a-zA-Z]+>", metaData.getRequest().getRoute()); + Assert.assertEquals(Framework.PLAY.name(), metaData.getMetaData().getFramework()); + } + + private void makeRequest(String path) throws IOException { + HttpURLConnection conn = ((HttpURLConnection) serverRule.getEndpoint(path).openConnection()); + conn.connect(); + System.out.println(conn.getResponseCode()); + } + + private void verifyUserClassDetection(SecurityMetaData metaData, String methodName) { Assert.assertNotNull(metaData.getMetaData()); Assert.assertTrue(metaData.getMetaData().isUserLevelServiceMethodEncountered()); StackTraceElement element = metaData.getCustomAttribute(GenericHelper.USER_CLASS_ENTITY, StackTraceElement.class); Assert.assertNotNull(element); Assert.assertEquals(SimpleJavaController.class.getName(), element.getClassName()); - Assert.assertEquals("hello", element.getMethodName()); + Assert.assertEquals(methodName, element.getMethodName()); } - private void assertMappings(ApplicationURLMapping actualMapping){ Assert.assertNotNull(actualMapping.getPath()); Assert.assertNotNull(actualMapping.getHandler()); @@ -81,7 +119,7 @@ private void assertMappings(ApplicationURLMapping actualMapping){ String path = actualMapping.getPath(); String handler = expectedMappings.get(path); - String method = !path.equals("/post") ? "GET" : "POST"; + String method = "GET"; Assert.assertEquals(handler, actualMapping.getHandler()); Assert.assertEquals(method, actualMapping.getMethod()); diff --git a/instrumentation-security/play-2.6/src/test/resources/conf/routes b/instrumentation-security/play-2.6/src/test/resources/conf/routes index 7af0d11ef..99a1ece7d 100644 --- a/instrumentation-security/play-2.6/src/test/resources/conf/routes +++ b/instrumentation-security/play-2.6/src/test/resources/conf/routes @@ -2,4 +2,5 @@ GET /hello com.nr.agent.security.instrumentation.play26.SimpleJavaC 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 +GET /post/:data com.nr.agent.security.instrumentation.play26.SimpleJavaController.post(data: String) +GET /post1/$data<[a-zA-Z]+> com.nr.agent.security.instrumentation.play26.SimpleJavaController.post(data: String) \ No newline at end of file From 860024a9c5a511d0f3ecb757a667a701dff3a3ce Mon Sep 17 00:00:00 2001 From: Ishika Dawda <112611034+IshikaDawda@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:35:42 +0530 Subject: [PATCH 062/122] NR-274559 Add key identifiers in all the JSONs (#264) * NR-274559 : Add key identifiers in all JSONs & Json Version bump to 1.2.4 --- gradle.properties | 2 +- .../IASTDataTransferRequestProcessor.java | 10 ++++-- ...MonitorGrpcFuzzFailRequestQueueThread.java | 4 +-- .../instrumentator/httpclient/RestClient.java | 5 ++- .../utils/ApplicationInfoUtils.java | 2 +- .../models/IASTDataTransferRequest.java | 18 +++++++++++ .../models/javaagent/AgentBasicInfo.java | 31 ++++++++++++++++--- .../models/javaagent/ApplicationInfoBean.java | 16 +--------- .../javaagent/ApplicationURLMappings.java | 9 ------ .../models/javaagent/ErrorIncident.java | 10 ------ .../models/javaagent/ExitEventBean.java | 11 ------- .../models/javaagent/FuzzFailEvent.java | 13 +------- .../models/javaagent/HttpConnectionStat.java | 13 +------- .../models/javaagent/JAHealthCheck.java | 18 ----------- .../javaagent/JavaAgentDynamicPathBean.java | 12 +------ .../models/javaagent/JavaAgentEventBean.java | 15 --------- .../models/javaagent/LogMessage.java | 24 ++++++++++++++ .../models/javaagent/ShutDownEvent.java | 16 ---------- 18 files changed, 85 insertions(+), 144 deletions(-) diff --git a/gradle.properties b/gradle.properties index 8e99a4eca..dec247fde 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # The agent version. agentVersion=1.4.0 -jsonVersion=1.2.3 +jsonVersion=1.2.4 # Updated exposed NR APM API version. nrAPIVersion=8.12.0 diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java index 628b2cf99..c4c732798 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java @@ -1,5 +1,8 @@ package com.newrelic.agent.security.instrumentator.httpclient; +import com.newrelic.agent.security.AgentConfig; +import com.newrelic.agent.security.AgentInfo; +import com.newrelic.agent.security.instrumentator.utils.INRSettingsKey; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.models.IASTDataTransferRequest; @@ -10,14 +13,13 @@ import com.newrelic.api.agent.NewRelic; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GrpcClientRequestReplayHelper; +import org.apache.commons.lang3.StringUtils; import java.time.Instant; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.HashSet; -import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -91,6 +93,10 @@ private void task() { if (batchSize > 100 && remainingRecordCapacity > batchSize) { request = new IASTDataTransferRequest(NewRelicSecurity.getAgent().getAgentUUID()); + if (AgentConfig.getInstance().getConfig().getCustomerInfo() != null) { + request.setAppAccountId(AgentConfig.getInstance().getConfig().getCustomerInfo().getAccountId()); + } + request.setAppEntityGuid(AgentInfo.getInstance().getLinkingMetadata().getOrDefault(INRSettingsKey.NR_ENTITY_GUID, StringUtils.EMPTY)); request.setBatchSize(batchSize); request.setCompletedRequests(getEffectiveCompletedRequests()); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/MonitorGrpcFuzzFailRequestQueueThread.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/MonitorGrpcFuzzFailRequestQueueThread.java index baf52fc99..16473fd75 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/MonitorGrpcFuzzFailRequestQueueThread.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/MonitorGrpcFuzzFailRequestQueueThread.java @@ -1,7 +1,5 @@ package com.newrelic.agent.security.instrumentator.httpclient; -import com.newrelic.agent.security.AgentInfo; -import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.models.javaagent.FuzzFailEvent; import com.newrelic.agent.security.intcodeagent.websocket.EventSendPool; import com.newrelic.api.agent.security.instrumentation.helpers.GrpcClientRequestReplayHelper; @@ -23,7 +21,7 @@ public void run() { // TODO: Add to fuzz fail count in HC and remove FuzzFailEvent if not needed. Map fuzzFailMap = GrpcClientRequestReplayHelper.getInstance().getSingleRequestFromFuzzFailRequestQueue(); FuzzRequestBean request = (FuzzRequestBean) fuzzFailMap.keySet().toArray()[0]; - FuzzFailEvent fuzzFailEvent = new FuzzFailEvent(AgentInfo.getInstance().getApplicationUUID()); + FuzzFailEvent fuzzFailEvent = new FuzzFailEvent(); fuzzFailEvent.setFuzzHeader(request.getHeaders().get(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID)); EventSendPool.getInstance().sendEvent(fuzzFailEvent); } catch (InterruptedException e) { 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 909775771..726ea5f3e 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 @@ -1,6 +1,5 @@ package com.newrelic.agent.security.instrumentator.httpclient; -import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; import com.newrelic.agent.security.intcodeagent.models.FuzzRequestBean; @@ -137,7 +136,7 @@ public void fireRequest(FuzzRequestBean httpRequest, List endpoints, int 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 fuzzFailEvent = new FuzzFailEvent(); fuzzFailEvent.setFuzzHeader(request.header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID)); EventSendPool.getInstance().sendEvent(fuzzFailEvent); } @@ -228,7 +227,7 @@ else if(response.code() >= 400){ 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 fuzzFailEvent = new FuzzFailEvent(); fuzzFailEvent.setFuzzHeader(request.header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID)); EventSendPool.getInstance().sendEvent(fuzzFailEvent); } catch (Exception e){ diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/ApplicationInfoUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/ApplicationInfoUtils.java index 0c3f2efcc..a5fd967e6 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/ApplicationInfoUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/utils/ApplicationInfoUtils.java @@ -210,7 +210,7 @@ public static ApplicationInfoBean createApplicationInfoBean(Identifier identifie AgentUtils.getInstance().getStatusLogValues().put(PROCESS_BINARY, NOT_AVAILABLE); try { RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); - ApplicationInfoBean applicationInfoBean = new ApplicationInfoBean(vmpid, applicationUUID, STATIC); + ApplicationInfoBean applicationInfoBean = new ApplicationInfoBean(vmpid, STATIC); applicationInfoBean.setStartTime(runtimeMXBean.getStartTime()); identifier.setCollectorIp(getIpAddress()); // TODO: Need to write platform agnostic alternative for this. diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/IASTDataTransferRequest.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/IASTDataTransferRequest.java index 9a7fe3b02..f7ab3430d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/IASTDataTransferRequest.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/IASTDataTransferRequest.java @@ -11,6 +11,8 @@ public class IASTDataTransferRequest { private String jsonName = "iast-data-request"; private String applicationUUID; + private String appAccountId; + private String appEntityGuid; private int batchSize; @@ -65,6 +67,22 @@ public void setJsonName(String jsonName) { this.jsonName = jsonName; } + public String getAppAccountId() { + return appAccountId; + } + + public void setAppAccountId(String appAccountId) { + this.appAccountId = appAccountId; + } + + public String getAppEntityGuid() { + return appEntityGuid; + } + + public void setAppEntityGuid(String appEntityGuid) { + this.appEntityGuid = appEntityGuid; + } + @Override public String toString() { try { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java index 5c204b402..edd2a1acf 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/AgentBasicInfo.java @@ -60,6 +60,9 @@ public class AgentBasicInfo { private String eventType; private Map linkingMetadata; + private String appAccountId; + private String appEntityGuid; + private String applicationUUID; @JsonInclude private static String policyVersion; @@ -79,7 +82,9 @@ public AgentBasicInfo() { setGroupName(AgentConfig.getInstance().getGroupName()); setNodeId(AgentInfo.getInstance().getLinkingMetadata().getOrDefault(INRSettingsKey.NR_ENTITY_GUID, StringUtils.EMPTY)); setLinkingMetadata(new HashMap<>(AgentInfo.getInstance().getLinkingMetadata())); - setAccountId(AgentConfig.getInstance().getConfig().getCustomerInfo().getAccountId()); + setAppEntityGuid(AgentInfo.getInstance().getLinkingMetadata().getOrDefault(INRSettingsKey.NR_ENTITY_GUID, StringUtils.EMPTY)); + setAppAccountId(AgentConfig.getInstance().getConfig().getCustomerInfo().getAccountId()); + setApplicationUUID(AgentInfo.getInstance().getApplicationUUID()); if (this instanceof ApplicationInfoBean) { setJsonName(JSON_NAME_APPLICATION_INFO_BEAN); } else if (this instanceof JavaAgentEventBean) { @@ -240,11 +245,27 @@ public void setLinkingMetadata(Map linkingMetadata) { this.linkingMetadata = linkingMetadata; } - public String getAccountId() { - return accountId; + public String getAppAccountId() { + return appAccountId; } - public void setAccountId(String accountId) { - this.accountId = accountId; + public void setAppAccountId(String appAccountId) { + this.appAccountId = appAccountId; + } + + public String getAppEntityGuid() { + return appEntityGuid; + } + + public void setAppEntityGuid(String appEntityGuid) { + this.appEntityGuid = appEntityGuid; + } + + public String getApplicationUUID() { + return applicationUUID; + } + + public void setApplicationUUID(String applicationUUID) { + this.applicationUUID = applicationUUID; } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationInfoBean.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationInfoBean.java index 3f2620adf..f5732752a 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationInfoBean.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ApplicationInfoBean.java @@ -22,11 +22,6 @@ public class ApplicationInfoBean extends AgentBasicInfo { */ private Integer pid; - /** - * UUID per running application. - */ - private String applicationUUID; - /** * name of running application. */ @@ -79,10 +74,9 @@ public void setLibraryPath(List libraryPath) { private Identifier identifier; - public ApplicationInfoBean(Integer pid, String applicationUUID, String agentAttachmentType) { + public ApplicationInfoBean(Integer pid, String agentAttachmentType) { super(); this.pid = pid; - this.applicationUUID = applicationUUID; this.runCommand = System.getProperty("sun.java.command"); this.userDir = System.getProperty("user.dir"); this.libraryPath = new ArrayList(); @@ -121,14 +115,6 @@ public void setPid(Integer pid) { this.pid = pid; } - public String getApplicationUUID() { - return applicationUUID; - } - - public void setApplicationUUID(String applicationUUID) { - this.applicationUUID = applicationUUID; - } - public String getApplicationName() { return applicationName; } 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 a65c8177c..6dec9b791 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,7 +7,6 @@ public class ApplicationURLMappings extends AgentBasicInfo{ - private String applicationUUID; private Set mappings; public ApplicationURLMappings(Set mappings) { @@ -26,12 +25,4 @@ 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; - } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ErrorIncident.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ErrorIncident.java index ed8b21988..0e8669f4b 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ErrorIncident.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ErrorIncident.java @@ -11,8 +11,6 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class ErrorIncident extends AgentBasicInfo { - private String applicationUUID = AgentInfo.getInstance().getApplicationUUID(); - private LogMessageException exception; private Map linkingMetadata; @@ -23,14 +21,6 @@ public class ErrorIncident extends AgentBasicInfo { private HttpRequest httpRequest; - public String getApplicationUUID() { - return applicationUUID; - } - - public void setApplicationUUID(String applicationUUID) { - this.applicationUUID = applicationUUID; - } - public LogMessageException getException() { return exception; } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ExitEventBean.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ExitEventBean.java index c2ae85524..02030da4a 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ExitEventBean.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ExitEventBean.java @@ -7,8 +7,6 @@ public class ExitEventBean extends AgentBasicInfo { private String executionId; private String caseType; private String k2RequestIdentifier; - private String applicationUUID; - public ExitEventBean() { super(); } @@ -17,7 +15,6 @@ public ExitEventBean(String executionId, String caseType) { this(); this.executionId = executionId; this.caseType = caseType; - this.applicationUUID = AgentInfo.getInstance().getApplicationUUID(); } public String getExecutionId() { @@ -44,14 +41,6 @@ public void setK2RequestIdentifier(String k2RequestIdentifier) { this.k2RequestIdentifier = k2RequestIdentifier; } - public String getApplicationUUID() { - return applicationUUID; - } - - public void setApplicationUUID(String applicationUUID) { - this.applicationUUID = applicationUUID; - } - @Override public String toString() { return JsonConverter.toJSON(this); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/FuzzFailEvent.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/FuzzFailEvent.java index 2fcb30a63..88150b81d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/FuzzFailEvent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/FuzzFailEvent.java @@ -6,19 +6,8 @@ public class FuzzFailEvent extends AgentBasicInfo { private String fuzzHeader; - private String applicationUUID; - - public String getApplicationUUID() { - return applicationUUID; - } - - public void setApplicationUUID(String applicationUUID) { - this.applicationUUID = applicationUUID; - } - - public FuzzFailEvent(String applicationUUID) { + public FuzzFailEvent() { super(); - this.applicationUUID = applicationUUID; } public String getFuzzHeader() { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/HttpConnectionStat.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/HttpConnectionStat.java index e8a452c1b..7bc6f2d2c 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/HttpConnectionStat.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/HttpConnectionStat.java @@ -8,13 +8,10 @@ public class HttpConnectionStat extends AgentBasicInfo { private Collection httpConnections; - private String applicationUUID; - private Boolean isCached; - public HttpConnectionStat(Collection httpConnections, String applicationUUID, Boolean isCached) { + public HttpConnectionStat(Collection httpConnections, Boolean isCached) { this.httpConnections = httpConnections; - this.applicationUUID = applicationUUID; this.isCached = isCached; } @@ -34,14 +31,6 @@ public void setIsCached(Boolean isCached) { this.isCached = isCached; } - public String getApplicationUUID() { - return applicationUUID; - } - - public void setApplicationUUID(String applicationUUID) { - this.applicationUUID = applicationUUID; - } - public String toString() { return JsonConverter.toJSON(this); } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java index da4d409cf..1e5fb9072 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java @@ -14,8 +14,6 @@ public class JAHealthCheck extends AgentBasicInfo { private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); private static final String HC_CREATED = "Created Health Check: %s"; - private String applicationUUID; - // private String protectedServer; // private Set protectedDB; @@ -60,7 +58,6 @@ public class JAHealthCheck extends AgentBasicInfo { public JAHealthCheck(String applicationUUID) { super(); - this.applicationUUID = applicationUUID; this.invokedHookCount = new AtomicInteger(0); this.eventDropCount = new AtomicInteger(0); this.eventProcessed = new AtomicInteger(0); @@ -83,7 +80,6 @@ public JAHealthCheck(String applicationUUID) { public JAHealthCheck(JAHealthCheck jaHealthCheck) { super(); - this.applicationUUID = jaHealthCheck.applicationUUID; this.invokedHookCount = new AtomicInteger(jaHealthCheck.invokedHookCount.intValue()); this.eventDropCount = new AtomicInteger(jaHealthCheck.eventDropCount.intValue()); this.eventProcessed = new AtomicInteger(jaHealthCheck.eventProcessed.intValue()); @@ -113,20 +109,6 @@ public void setKind(IdentifierEnvs kind) { this.kind = kind; } - /** - * @return the applicationUUID - */ - public String getApplicationUUID() { - return applicationUUID; - } - - /** - * @param applicationUUID the applicationUUID to set - */ - public void setApplicationUUID(String applicationUUID) { - this.applicationUUID = applicationUUID; - } - /** * @return the eventDropCount */ diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JavaAgentDynamicPathBean.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JavaAgentDynamicPathBean.java index f6e207f6c..6f84a2ecf 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JavaAgentDynamicPathBean.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JavaAgentDynamicPathBean.java @@ -5,7 +5,6 @@ public class JavaAgentDynamicPathBean extends AgentBasicInfo { - private String applicationUUID; private String workingDirectory; @@ -13,22 +12,13 @@ public class JavaAgentDynamicPathBean extends AgentBasicInfo { private JSONArray dynamicPaths; - public JavaAgentDynamicPathBean(String applicationUUID, String workingDirectory, JSONArray jarPaths, JSONArray dynamicPaths) { + public JavaAgentDynamicPathBean(String workingDirectory, JSONArray jarPaths, JSONArray dynamicPaths) { super(); - this.applicationUUID = applicationUUID; this.workingDirectory = workingDirectory; this.jarPaths = jarPaths; this.dynamicPaths = dynamicPaths; } - public String getApplicationUUID() { - return applicationUUID; - } - - public void setApplicationUUID(String applicationUUID) { - this.applicationUUID = applicationUUID; - } - public String getWorkingDirectory() { return workingDirectory; } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JavaAgentEventBean.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JavaAgentEventBean.java index 76a7deb65..319fdabd0 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JavaAgentEventBean.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JavaAgentEventBean.java @@ -9,7 +9,6 @@ public class JavaAgentEventBean extends AgentBasicInfo { private Integer pid; - private String applicationUUID; private Long startTime; private String sourceMethod; private String userFileName; @@ -158,20 +157,6 @@ public void setEventGenerationTime(Long eventGenerationTime) { this.eventGenerationTime = eventGenerationTime; } - /** - * @return the applicationUUID - */ - public String getApplicationUUID() { - return applicationUUID; - } - - /** - * @param applicationUUID the applicationUUID to set - */ - public void setApplicationUUID(String applicationUUID) { - this.applicationUUID = applicationUUID; - } - /** * @return the servletInfo */ diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/LogMessage.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/LogMessage.java index 4e09c7621..3e7886af7 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/LogMessage.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/LogMessage.java @@ -1,8 +1,11 @@ package com.newrelic.agent.security.intcodeagent.models.javaagent; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.newrelic.agent.security.AgentConfig; import com.newrelic.agent.security.AgentInfo; +import com.newrelic.agent.security.instrumentator.utils.INRSettingsKey; import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; +import org.apache.commons.lang3.StringUtils; import java.time.Instant; import java.util.Map; @@ -26,6 +29,8 @@ public class LogMessage { private Map linkingMetadata; private String threadName; + private String appAccountId; + private String appEntityGuid; public LogMessage(String level, String message, String caller, Throwable exception, Map linkingMetadata) { this.timestamp = Instant.now().toEpochMilli(); @@ -37,6 +42,10 @@ public LogMessage(String level, String message, String caller, Throwable excepti this.exception = new LogMessageException(exception, 0, 1); } this.threadName = Thread.currentThread().getName(); + this.appEntityGuid = AgentInfo.getInstance().getLinkingMetadata().getOrDefault(INRSettingsKey.NR_ENTITY_GUID, StringUtils.EMPTY); + if (AgentConfig.getInstance().getConfig().getCustomerInfo() != null) { + this.appAccountId = AgentConfig.getInstance().getConfig().getCustomerInfo().getAccountId(); + } } public Long getTimestamp() { @@ -89,6 +98,21 @@ public void setThreadName(String threadName) { this.threadName = threadName; } + public String getAppAccountId() { + return appAccountId; + } + + public void setAppAccountId(String appAccountId) { + this.appAccountId = appAccountId; + } + + public String getAppEntityGuid() { + return appEntityGuid; + } + + public void setAppEntityGuid(String appEntityGuid) { + this.appEntityGuid = appEntityGuid; + } @Override public String toString() { return JsonConverter.toJSON(this); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ShutDownEvent.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ShutDownEvent.java index 2e81a122d..4a5e63844 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ShutDownEvent.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/ShutDownEvent.java @@ -9,8 +9,6 @@ public class ShutDownEvent extends AgentBasicInfo implements Serializable { private static final long serialVersionUID = -2320594688008671870L; - private String applicationUUID; - private String status; private JSONArray resonForTermination; @@ -21,20 +19,6 @@ public ShutDownEvent() { super(); } - /** - * @return the applicationUUID - */ - public String getApplicationUUID() { - return applicationUUID; - } - - /** - * @param applicationUUID the applicationUUID to set - */ - public void setApplicationUUID(String applicationUUID) { - this.applicationUUID = applicationUUID; - } - /** * @return the status */ From aa7d23dd6316945cc087d6157f9b406e740a0841 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 9 Aug 2024 15:45:36 +0530 Subject: [PATCH 063/122] Set HC sending interval to 5 min --- .../intcodeagent/logging/HealthCheckScheduleThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java index a33da7bbe..71208cc35 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java @@ -122,7 +122,7 @@ private ThreadPoolStats populateThreadPoolStats() { private HealthCheckScheduleThread() {} public void scheduleNewTask() { - future = SchedulerHelper.getInstance().scheduleHealthCheck(runnable, 30, 30, TimeUnit.SECONDS); + future = SchedulerHelper.getInstance().scheduleHealthCheck(runnable, 30, 300, TimeUnit.SECONDS); } public boolean cancelTask(boolean forceCancel) { From c9454f117665de8d3db594e0bb8f2e2932263cca Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 9 Aug 2024 15:56:39 +0530 Subject: [PATCH 064/122] code refactoring --- .../newrelic/agent/security/intcodeagent/websocket/WSClient.java | 1 + 1 file changed, 1 insertion(+) 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 ddf255f3a..cac5a964a 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 @@ -2,6 +2,7 @@ import com.newrelic.agent.security.AgentConfig; 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; From 1ea18fd6bc69ecfdbffa2d526e4895d2b1cf4b2c Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 9 Aug 2024 16:39:04 +0530 Subject: [PATCH 065/122] NR-299885: Instrumentation support for GraphQL --- .../graphql-java-16.2/build.gradle | 22 +++++++++++++ .../java/graphql/GraphQL_Instrumentation.java | 32 +++++++++++++++++++ .../ParseAndValidate_Instrumentation.java | 9 ++++++ .../agent/security/schema/HttpRequest.java | 11 +++++++ .../schema/HttpRequestCustomDataTypeEnum.java | 8 +++++ settings.gradle | 3 +- 6 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 instrumentation-security/graphql-java-16.2/build.gradle create mode 100644 instrumentation-security/graphql-java-16.2/src/main/java/graphql/GraphQL_Instrumentation.java create mode 100644 instrumentation-security/graphql-java-16.2/src/main/java/graphql/ParseAndValidate_Instrumentation.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequestCustomDataTypeEnum.java diff --git a/instrumentation-security/graphql-java-16.2/build.gradle b/instrumentation-security/graphql-java-16.2/build.gradle new file mode 100644 index 000000000..2ac60f459 --- /dev/null +++ b/instrumentation-security/graphql-java-16.2/build.gradle @@ -0,0 +1,22 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + implementation("com.graphql-java:graphql-java:16.2") +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.graphql-java-16.2' } +} + +verifyInstrumentation { + passesOnly('com.graphql-java:graphql-java:[16.0,)') + excludeRegex('com.graphql-java:graphql-java:(0.0.0|201|202).*') + excludeRegex('com.graphql-java:graphql-java:.*(vTEST|-beta|-alpha1|-nf-execution|-rc|-TEST).*') + exclude('com.graphql-java:graphql-java:15.0') +} + +site { + title 'GraphQL Java' + type 'Framework' +} diff --git a/instrumentation-security/graphql-java-16.2/src/main/java/graphql/GraphQL_Instrumentation.java b/instrumentation-security/graphql-java-16.2/src/main/java/graphql/GraphQL_Instrumentation.java new file mode 100644 index 000000000..235a47d4c --- /dev/null +++ b/instrumentation-security/graphql-java-16.2/src/main/java/graphql/GraphQL_Instrumentation.java @@ -0,0 +1,32 @@ +package graphql; + +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.HttpRequest; +import com.newrelic.api.agent.security.schema.HttpRequestCustomDataTypeEnum; +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import graphql.execution.instrumentation.InstrumentationState; +import graphql.language.Document; +import graphql.schema.GraphQLSchema; + +import java.util.concurrent.CompletableFuture; + +@Weave(originalName = "graphql.GraphQL", type = MatchType.ExactClass) +public class GraphQL_Instrumentation { + + private CompletableFuture execute(ExecutionInput executionInput, Document document, GraphQLSchema graphQLSchema, InstrumentationState instrumentationState) { + try { + if (NewRelicSecurity.isHookProcessingActive()) { + HttpRequest request = NewRelicSecurity.getAgent().getSecurityMetaData().getRequest(); + if (executionInput.getQuery() != null && !executionInput.getQuery().isEmpty()) { + request.getCustomDataType().put("*.query", HttpRequestCustomDataTypeEnum.GRAPHQL_QUERY.name()); + } + if (executionInput.getQuery() != null && !executionInput.getVariables().isEmpty()) { + request.getCustomDataType().put("*.variables", HttpRequestCustomDataTypeEnum.GRAPHQL_VARIABLE.name()); + } + } + } catch (Exception ignored) {} + return Weaver.callOriginal(); + } +} diff --git a/instrumentation-security/graphql-java-16.2/src/main/java/graphql/ParseAndValidate_Instrumentation.java b/instrumentation-security/graphql-java-16.2/src/main/java/graphql/ParseAndValidate_Instrumentation.java new file mode 100644 index 000000000..84c3ddf2b --- /dev/null +++ b/instrumentation-security/graphql-java-16.2/src/main/java/graphql/ParseAndValidate_Instrumentation.java @@ -0,0 +1,9 @@ +package graphql; + +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; + +@Weave(originalName = "graphql.ParseAndValidate", type = MatchType.ExactClass) +public class ParseAndValidate_Instrumentation { + +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java index 5b65ef0f6..f81bb66d8 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequest.java @@ -32,9 +32,13 @@ public class HttpRequest { private Map pathParameterMap; private boolean isRequestParsed; + private boolean isGrpc; + private String route; + private Map customDataType; + public HttpRequest() { this.clientIP = StringUtils.EMPTY; this.body = new StringBuilder(); @@ -50,6 +54,7 @@ public HttpRequest() { this.isRequestParsed = false; this.isGrpc = false; this.route = StringUtils.EMPTY; + this.customDataType = new HashMap<>(); } public HttpRequest(HttpRequest servletInfo) { @@ -67,6 +72,7 @@ public HttpRequest(HttpRequest servletInfo) { this.isRequestParsed = servletInfo.isRequestParsed; this.isGrpc = servletInfo.isGrpc; this.route = servletInfo.route; + this.customDataType = servletInfo.customDataType; } public String getMethod() { @@ -229,6 +235,11 @@ public void setRoute(String segment, boolean isAlreadyServlet) { this.route = Paths.get(this.route, formatedSegment).normalize().toString(); } } + + public Map getCustomDataType() { + return customDataType; + } + } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequestCustomDataTypeEnum.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequestCustomDataTypeEnum.java new file mode 100644 index 000000000..473eefc83 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/HttpRequestCustomDataTypeEnum.java @@ -0,0 +1,8 @@ +package com.newrelic.api.agent.security.schema; + +public enum HttpRequestCustomDataTypeEnum { + GRAPHQL_QUERY, + GRAPHQL_VARIABLE, + + NONE; +} diff --git a/settings.gradle b/settings.gradle index 5cbeccc44..d7bad818d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -209,4 +209,5 @@ include 'instrumentation:weblogic-12.2' include 'instrumentation:jedis-4.0.0' include 'instrumentation:jedis-3.0.0' include 'instrumentation:jedis-2.7.1_2.7.2' -include 'instrumentation:jedis-1.4.0' \ No newline at end of file +include 'instrumentation:jedis-1.4.0' +include 'instrumentation:graphql-java-16.2' \ No newline at end of file From 815009899a78abb0e2e18809414de50c83ce7a4f Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 9 Aug 2024 17:18:35 +0530 Subject: [PATCH 066/122] send skip scan parameter in each event --- .../newrelic/agent/security/AgentConfig.java | 21 +++++++++++++++++-- .../instrumentator/dispatcher/Dispatcher.java | 4 ++++ .../agent/security/schema/AgentMetaData.java | 18 ++++++++++++---- 3 files changed, 37 insertions(+), 6 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 57faaa6d8..f92150994 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 @@ -45,6 +45,7 @@ public class AgentConfig { public static final String ACCOUNT_ID_LOCATION = "account_id_location"; public static final String ACCOUNT_ID_KEY = "account_id_key"; public static final String ROUTE = "route"; + public static final String MAPPING_PARAMETERS_ARE_REQUIRED_FOR_IAST_RESTRICTED_MODE = "Mapping Parameters are required for IAST Restricted Mode"; private String NR_CSEC_HOME; private String logLevel; @@ -98,7 +99,7 @@ public long trigerIAST() { return date-currentTime; } } catch (Exception e){ - //TODO send notice error + NewRelic.noticeError(new RestrictionModeException("Error while calculating next scan time for IAST Restricted Mode", e), Agent.getCustomNoticeErrorParameters(), true); System.err.println("[NR-CSEC-JA] Error while calculating next scan time for IAST Restricted Mode. IAST Restricted Mode will be disabled."); NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while calculating next scan time for IAST Restricted Mode. IAST Restricted Mode will be disabled."); return Long.MAX_VALUE; @@ -118,11 +119,12 @@ private void instantiateAgentMode(String groupName) { case IAST_RESTRICTED: try { readIastRestrictedConfig(); + updateSkipScanParameters(); } catch (RestrictionModeException e) { System.err.println("[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled."); NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled."); NewRelic.noticeError(e, Agent.getCustomNoticeErrorParameters(), true); - this.agentMode.getIastScan().setEnabled(false); + AgentInfo.getInstance().agentStatTrigger(false); } break; default: @@ -132,6 +134,18 @@ private void instantiateAgentMode(String groupName) { } + private void updateSkipScanParameters() { + for (MappingParameters mappingParameter : this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters()) { + if(mappingParameter.getAccountIdLocation().equals(HttpParameterLocation.HEADER)){ + this.agentMode.getIastScan().getRestrictionCriteria().getSkipScanParameters().getHeader().add(mappingParameter.getAccountIdKey()); + } else if(mappingParameter.getAccountIdLocation().equals(HttpParameterLocation.QUERY)){ + this.agentMode.getIastScan().getRestrictionCriteria().getSkipScanParameters().getQuery().add(mappingParameter.getAccountIdKey()); + } else if(mappingParameter.getAccountIdLocation().equals(HttpParameterLocation.BODY)){ + this.agentMode.getIastScan().getRestrictionCriteria().getSkipScanParameters().getBody().add(mappingParameter.getAccountIdKey()); + } + } + } + private void readIastConfig() { this.agentMode.getIastScan().setEnabled(true); this.agentMode.getRaspScan().setEnabled(false); @@ -160,6 +174,9 @@ private void readIastRestrictedConfig() throws RestrictionModeException { //Mapping parameters List> mappingParameters = NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS, Collections.emptyList()); + if(mappingParameters.isEmpty()) { + throw new RestrictionModeException(MAPPING_PARAMETERS_ARE_REQUIRED_FOR_IAST_RESTRICTED_MODE); + } for (Map mappingParameter : mappingParameters) { MappingParameters matchingCriteria = new MappingParameters(HttpParameterLocation.valueOf(mappingParameter.get(ACCOUNT_ID_LOCATION)), mappingParameter.get(ACCOUNT_ID_KEY)); // MappingParameters matchingCriteria = mapper.convertValue(mappingParameter, MappingParameters.class); 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 9aa06df9e..5766ea20b 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 @@ -1,6 +1,7 @@ package com.newrelic.agent.security.instrumentator.dispatcher; import com.google.gson.Gson; +import com.newrelic.agent.security.AgentConfig; import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.helper.DynamoDBRequestConverter; import com.newrelic.agent.security.instrumentator.utils.AgentUtils; @@ -720,6 +721,9 @@ private JavaAgentEventBean setGenericProperties(AbstractOperation objectBean, Ja private JavaAgentEventBean prepareEvent(HttpRequest httpRequestBean, AgentMetaData metaData, VulnerabilityCaseType vulnerabilityCaseType, K2RequestIdentifier k2RequestIdentifier) { + if(AgentConfig.getInstance().getAgentMode().getIastScan().getRestricted()) { + metaData.setSkipScanParameters(AgentConfig.getInstance().getAgentMode().getIastScan().getRestrictionCriteria().getSkipScanParameters()); + } JavaAgentEventBean eventBean = new JavaAgentEventBean(); eventBean.setHttpRequest(httpRequestBean); eventBean.setMetaData(metaData); 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 e7362aa95..dd35b63b0 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 @@ -1,11 +1,9 @@ package com.newrelic.api.agent.security.schema; import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; +import com.newrelic.api.agent.security.schema.policy.SkipScanParameters; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; public class AgentMetaData { @@ -26,6 +24,8 @@ public class AgentMetaData { private Map reflectedMetaData; + private SkipScanParameters skipScanParameters; + @JsonIgnore private StackTraceElement[] serviceTrace; @@ -56,6 +56,7 @@ public AgentMetaData() { this.reflectedMetaData = new HashMap<>(); this.appServerInfo = new AppServerInfo(); this.framework = StringUtils.EMPTY; + this.skipScanParameters = new SkipScanParameters(); } public AgentMetaData(AgentMetaData agentMetaData) { @@ -77,6 +78,7 @@ public AgentMetaData(AgentMetaData agentMetaData) { this.foundAnnotedUserLevelServiceMethod = agentMetaData.foundAnnotedUserLevelServiceMethod; this.fromJumpRequiredInStackTrace = agentMetaData.getFromJumpRequiredInStackTrace(); this.framework = agentMetaData.framework; + this.skipScanParameters = agentMetaData.skipScanParameters; } public boolean isTriggerViaRCI() { @@ -219,4 +221,12 @@ public void setFramework(Framework framework) { this.framework = framework.name(); } } + + public SkipScanParameters getSkipScanParameters() { + return skipScanParameters; + } + + public void setSkipScanParameters(SkipScanParameters skipScanParameters) { + this.skipScanParameters = skipScanParameters; + } } From 5e03fd10db8b96dd1e15b7c4e27da2bc864bd0be Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 9 Aug 2024 17:53:58 +0530 Subject: [PATCH 067/122] fix for mismatch values of event sender submitted and completed. invoke reset of droppedEvents --- .../models/javaagent/EventStats.java | 1 + .../intcodeagent/websocket/EventSendPool.java | 19 +++++++++++++++---- .../newrelic/api/agent/security/Agent.java | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventStats.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventStats.java index 279dcb401..86465eb61 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventStats.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/EventStats.java @@ -36,6 +36,7 @@ public void reset(){ this.iastEvents.reset(); this.dispatcher.reset(); this.exitEvents.reset(); + this.droppedDueTo.reset(); } public String toString() { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java index 3dd718845..912599e4a 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java @@ -1,6 +1,7 @@ package com.newrelic.agent.security.intcodeagent.websocket; import com.newrelic.agent.security.AgentInfo; +import com.newrelic.agent.security.instrumentator.dispatcher.Dispatcher; import com.newrelic.agent.security.instrumentator.httpclient.RestRequestThreadPool; import com.newrelic.agent.security.intcodeagent.executor.CustomFutureTask; import com.newrelic.agent.security.intcodeagent.executor.CustomThreadPoolExecutor; @@ -44,11 +45,21 @@ private EventSendPool() { @Override protected void afterExecute(Runnable r, Throwable t) { try { - if (t != null) { - AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementError(); - } else { - AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementCompleted(); + if (r instanceof CustomFutureTask && ((CustomFutureTask) r).getTask() instanceof EventSender) { + EventSender task = (EventSender) ((CustomFutureTask) r).get(); + if(task.getEvent() instanceof JavaAgentEventBean){ + if (t != null) { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementError(); + } else { + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementCompleted(); + } + } } +// if (t != null) { +// AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementError(); +// } else { +// AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementCompleted(); +// } } catch (Throwable ignored){} super.afterExecute(r, t); } 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 3406be671..b4eb91b4d 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 @@ -298,7 +298,7 @@ public void registerOperation(AbstractOperation operation) { logger.log(LogLevel.FINEST, DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL + JsonConverter.toJSON(operation), Agent.class.getName()); - AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDroppedDueTo().getCsecInternalEvent(); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDroppedDueTo().incrementCsecInternalEvent(); return; } @@ -306,7 +306,7 @@ public void registerOperation(AbstractOperation operation) { logger.log(LogLevel.FINEST, DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL + JsonConverter.toJSON(operation), Agent.class.getName()); - AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDroppedDueTo().getNrInternalEvent(); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDroppedDueTo().incrementNrInternalEvent(); return; } From 60a4bdbd1da727dffa319ee1b33957c805eb67fc Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 9 Aug 2024 18:37:46 +0530 Subject: [PATCH 068/122] NR-299885: Instrumentation support for GraphQL --- .../src/main/java/graphql/GraphQL_Instrumentation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation-security/graphql-java-16.2/src/main/java/graphql/GraphQL_Instrumentation.java b/instrumentation-security/graphql-java-16.2/src/main/java/graphql/GraphQL_Instrumentation.java index 235a47d4c..bf6f1bbe8 100644 --- a/instrumentation-security/graphql-java-16.2/src/main/java/graphql/GraphQL_Instrumentation.java +++ b/instrumentation-security/graphql-java-16.2/src/main/java/graphql/GraphQL_Instrumentation.java @@ -22,7 +22,7 @@ private CompletableFuture execute(ExecutionInput executionInput if (executionInput.getQuery() != null && !executionInput.getQuery().isEmpty()) { request.getCustomDataType().put("*.query", HttpRequestCustomDataTypeEnum.GRAPHQL_QUERY.name()); } - if (executionInput.getQuery() != null && !executionInput.getVariables().isEmpty()) { + if (executionInput.getVariables() != null && !executionInput.getVariables().isEmpty()) { request.getCustomDataType().put("*.variables", HttpRequestCustomDataTypeEnum.GRAPHQL_VARIABLE.name()); } } From 26ba10443fe8adc691226f417695a10fb1c067e8 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 12 Aug 2024 13:43:54 +0530 Subject: [PATCH 069/122] fix for mismatch values of eventStats --- .../security/instrumentator/dispatcher/DispatcherPool.java | 1 + .../agent/security/intcodeagent/websocket/EventSendPool.java | 2 +- .../agent/security/intcodeagent/websocket/WSClient.java | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java index f317969a7..fe9498539 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java @@ -239,6 +239,7 @@ public void dispatchExitEvent(ExitEventBean exitEventBean) { securityMetaData.addCustomAttribute(NR_APM_TRACE_ID, traceMetadata.getTraceId()); securityMetaData.addCustomAttribute(NR_APM_SPAN_ID, traceMetadata.getSpanId()); this.executor.submit(new Dispatcher(exitEventBean)); + AgentInfo.getInstance().getJaHealthCheck().getEventStats().getDispatcher().incrementSubmitted(); AgentInfo.getInstance().getJaHealthCheck().getEventStats().getExitEvents().incrementSubmitted(); } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java index 912599e4a..ab9dc3650 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java @@ -46,7 +46,7 @@ private EventSendPool() { protected void afterExecute(Runnable r, Throwable t) { try { if (r instanceof CustomFutureTask && ((CustomFutureTask) r).getTask() instanceof EventSender) { - EventSender task = (EventSender) ((CustomFutureTask) r).get(); + EventSender task = (EventSender) ((CustomFutureTask) r).getTask(); if(task.getEvent() instanceof JavaAgentEventBean){ if (t != null) { AgentInfo.getInstance().getJaHealthCheck().getEventStats().getEventSender().incrementError(); 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 cac5a964a..36af31dd0 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 @@ -262,7 +262,7 @@ private static void cleanIASTState() { public void onMessage(String message) { // Receive communication from IC side. try { - AgentInfo.getInstance().getJaHealthCheck().getWebSocketConnectionStats().incrementMessagesSent(); + AgentInfo.getInstance().getJaHealthCheck().getWebSocketConnectionStats().incrementMessagesReceived(); if (logger.isLogLevelEnabled(LogLevel.FINEST)) { logger.log(LogLevel.FINEST, String.format(INCOMING_CONTROL_COMMAND_S, message), this.getClass().getName()); From ccf58f0906c7e40ec12bd424f2ee62c83db04469 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 12 Aug 2024 16:04:52 +0530 Subject: [PATCH 070/122] Update Secure Cookie Event Schema and generation logic --- .../HttpServletResponse_Instrumentation.java | 13 ++-- .../HttpServletResponse_Instrumentation.java | 13 ++-- .../HttpServletResponse_Instrumentation.java | 13 ++-- .../instrumentator/dispatcher/Dispatcher.java | 21 +++--- .../operation/SecureCookieOperation.java | 74 ------------------- 5 files changed, 35 insertions(+), 99 deletions(-) delete mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SecureCookieOperation.java diff --git a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/http/HttpServletResponse_Instrumentation.java b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/http/HttpServletResponse_Instrumentation.java index f94ba5081..204c7c31e 100644 --- a/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/http/HttpServletResponse_Instrumentation.java +++ b/instrumentation-security/servlet-2.4/src/main/java/javax/servlet/http/HttpServletResponse_Instrumentation.java @@ -9,7 +9,6 @@ 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.SecureCookieOperation; import com.newrelic.api.agent.security.schema.operation.SecureCookieOperationSet; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; @@ -56,12 +55,16 @@ private AbstractOperation preprocessSecurityHook(Cookie cookie, String className sameSiteStrict = StringUtils.containsIgnoreCase(cookie.getValue(), "SameSite=Strict"); } - SecureCookieOperation operation = new SecureCookieOperation(Boolean.toString(isSecure ), isSecure, isHttpOnly, sameSiteStrict, cookie.getValue(), className, methodName); - operation.setLowSeverityHook(true); - NewRelicSecurity.getAgent().registerOperation(operation); + SecureCookieOperationSet operations = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("SECURE_COOKIE_OPERATION", SecureCookieOperationSet.class); + if(operations == null){ + operations = new SecureCookieOperationSet(className, methodName);; + operations.setLowSeverityHook(true); + NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute("SECURE_COOKIE_OPERATION", operations); + } + operations.addOperation(cookie.getName(), cookie.getValue(), isSecure, isHttpOnly, sameSiteStrict); // NewRelicSecurity.getAgent().registerOperation(operation); - return operation; + return operations; } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, HttpServletHelper.SERVLET_2_4, e.getMessage()), e, HttpServletResponse_Instrumentation.class.getName()); diff --git a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/http/HttpServletResponse_Instrumentation.java b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/http/HttpServletResponse_Instrumentation.java index b81181ba4..186841c43 100644 --- a/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/http/HttpServletResponse_Instrumentation.java +++ b/instrumentation-security/servlet-5.0/src/main/java/jakarta/servlet/http/HttpServletResponse_Instrumentation.java @@ -9,7 +9,6 @@ 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.SecureCookieOperation; import com.newrelic.api.agent.security.schema.operation.SecureCookieOperationSet; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; @@ -56,12 +55,16 @@ private AbstractOperation preprocessSecurityHook(Cookie cookie, String className sameSiteStrict = StringUtils.containsIgnoreCase(cookie.getValue(), "SameSite=Strict"); } - SecureCookieOperation operation = new SecureCookieOperation(Boolean.toString(isSecure ), isSecure, isHttpOnly, sameSiteStrict, cookie.getValue(), className, methodName); - operation.setLowSeverityHook(true); - NewRelicSecurity.getAgent().registerOperation(operation); + SecureCookieOperationSet operations = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("SECURE_COOKIE_OPERATION", SecureCookieOperationSet.class); + if(operations == null){ + operations = new SecureCookieOperationSet(className, methodName);; + operations.setLowSeverityHook(true); + NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute("SECURE_COOKIE_OPERATION", operations); + } + operations.addOperation(cookie.getName(), cookie.getValue(), isSecure, isHttpOnly, sameSiteStrict); // NewRelicSecurity.getAgent().registerOperation(operation); - return operation; + return operations; } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, HttpServletHelper.SERVLET_5_0, e.getMessage()), e, HttpServletResponse_Instrumentation.class.getName()); diff --git a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/http/HttpServletResponse_Instrumentation.java b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/http/HttpServletResponse_Instrumentation.java index bf70e32d0..c42a612f4 100644 --- a/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/http/HttpServletResponse_Instrumentation.java +++ b/instrumentation-security/servlet-6.0/src/main/java/jakarta/servlet/http/HttpServletResponse_Instrumentation.java @@ -9,7 +9,6 @@ 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.SecureCookieOperation; import com.newrelic.api.agent.security.schema.operation.SecureCookieOperationSet; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; @@ -57,12 +56,16 @@ private AbstractOperation preprocessSecurityHook(Cookie cookie, String className sameSiteStrict = StringUtils.containsIgnoreCase(cookie.getValue(), "SameSite=Strict"); } - SecureCookieOperation operation = new SecureCookieOperation(Boolean.toString(isSecure ), isSecure, isHttpOnly, sameSiteStrict, cookie.getValue(), className, methodName); - operation.setLowSeverityHook(true); - NewRelicSecurity.getAgent().registerOperation(operation); + SecureCookieOperationSet operations = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("SECURE_COOKIE_OPERATION", SecureCookieOperationSet.class); + if(operations == null){ + operations = new SecureCookieOperationSet(className, methodName);; + operations.setLowSeverityHook(true); + NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute("SECURE_COOKIE_OPERATION", operations); + } + operations.addOperation(cookie.getName(), cookie.getValue(), isSecure, isHttpOnly, sameSiteStrict); // NewRelicSecurity.getAgent().registerOperation(operation); - return operation; + return operations; } catch (Throwable e) { if (e instanceof NewRelicSecurityException) { NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SECURITY_EXCEPTION_MESSAGE, HttpServletHelper.SERVLET_6_0, e.getMessage()), e, HttpServletResponse_Instrumentation.class.getName()); 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 e01b4727a..29e3e7669 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 @@ -186,7 +186,7 @@ public Object call() throws Exception { eventBean = prepareXPATHEvent(eventBean, xPathOperationalBean); break; case SECURE_COOKIE: - SecureCookieOperation secureCookieOperationalBean = (SecureCookieOperation) operation; + SecureCookieOperationSet secureCookieOperationalBean = (SecureCookieOperationSet) operation; eventBean = prepareSecureCookieEvent(eventBean, secureCookieOperationalBean); break; case TRUSTBOUNDARY: @@ -472,16 +472,17 @@ private JavaAgentEventBean prepareRandomEvent(JavaAgentEventBean eventBean, } private JavaAgentEventBean prepareSecureCookieEvent(JavaAgentEventBean eventBean, - SecureCookieOperation secureCookieOperationalBean) { + SecureCookieOperationSet secureCookieOperationalBean) { JSONArray params = new JSONArray(); - params.add(secureCookieOperationalBean.getValue()); - JSONObject cookie = new JSONObject(); - cookie.put(COOKIE_VALUE, secureCookieOperationalBean.getCookie()); - cookie.put(COOKIE_IS_SECURE, secureCookieOperationalBean.isSecure()); - cookie.put(COOKIE_IS_HTTP_ONLY, secureCookieOperationalBean.isHttpOnly()); - cookie.put(COOKIE_IS_SAME_SITE_STRICT, secureCookieOperationalBean.isSameSiteStrict()); - params.add(cookie); - + for (SecureCookieOperationSet.SecureCookieOperation secureCookieOperation : secureCookieOperationalBean.getOperations()) { + JSONObject cookie = new JSONObject(); + cookie.put(COOKIE_NAME, secureCookieOperation.getName()); + cookie.put(COOKIE_VALUE, secureCookieOperation.getValue()); + cookie.put(COOKIE_IS_SECURE, secureCookieOperation.isSecure()); + cookie.put(COOKIE_IS_HTTP_ONLY, secureCookieOperation.isHttpOnly()); + cookie.put(COOKIE_IS_SAME_SITE_STRICT, secureCookieOperation.isSameSiteStrict()); + params.add(cookie); + } eventBean.setParameters(params); return eventBean; } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SecureCookieOperation.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SecureCookieOperation.java deleted file mode 100644 index f35208953..000000000 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/operation/SecureCookieOperation.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.newrelic.api.agent.security.schema.operation; - -import com.newrelic.api.agent.security.schema.AbstractOperation; -import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; - -public class SecureCookieOperation extends AbstractOperation { - private String value; - - private boolean isSecure; - private boolean isHttpOnly; - private boolean isSameSiteStrict; - - private String cookie; - - public SecureCookieOperation(String value, String className, String methodName) { - super(className, methodName); - this.setCaseType(VulnerabilityCaseType.SECURE_COOKIE); - this.value = value; - } - - public SecureCookieOperation(String value, boolean isSecure, boolean isHttpOnly, boolean isSameSiteStrict, String cookie, String className, String methodName) { - this(value, className, methodName); - this.isSecure = isSecure; - this.isHttpOnly = isHttpOnly; - this.isSameSiteStrict = isSameSiteStrict; - this.cookie = cookie; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public boolean isSecure() { - return isSecure; - } - - public void setSecure(boolean secure) { - isSecure = secure; - } - - public boolean isHttpOnly() { - return isHttpOnly; - } - - public void setHttpOnly(boolean httpOnly) { - isHttpOnly = httpOnly; - } - - public boolean isSameSiteStrict() { - return isSameSiteStrict; - } - - public void setSameSiteStrict(boolean sameSiteStrict) { - isSameSiteStrict = sameSiteStrict; - } - - public String getCookie() { - return cookie; - } - - public void setCookie(String cookie) { - this.cookie = cookie; - } - - @Override - public boolean isEmpty() { - return (value == null || value.trim().isEmpty()); - } - -} \ No newline at end of file From 46472e9f380dc81d0ccbb872f9b1ed229d3a75b0 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 12 Aug 2024 16:23:23 +0530 Subject: [PATCH 071/122] Add Changelogs for Release 1.4.1 --- Changelog.md | 23 +++++++++++++++++++++++ gradle.properties | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 4a1b5233d..d4b3d9d08 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,29 @@ 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.4.1] - TBD +### Adds +- [PR-296](https://github.com/newrelic/csec-java-agent/pull/296) Apache Solr Support: The security agent now also supports Apache Solr Version 4.0.0 and above. [NR-288599](https://new-relic.atlassian.net/browse/) +- [PR-275](https://github.com/newrelic/csec-java-agent/pull/275) The maximum permissible size for a request body for scan will be set at 500KB. [NR-174195](https://new-relic.atlassian.net/browse/) +- [PR-306](https://github.com/newrelic/csec-java-agent/pull/306) Add csec prefix to all instrumentation Jar, this resolves CVE flagged by third party scanners on our instrumentation JARs. [NR-289249](https://new-relic.atlassian.net/browse/) +- [PR-303](https://github.com/newrelic/csec-java-agent/pull/303) Honour OFF Flag, Handle Boolean values for config log_level. [NR-293102](https://new-relic.atlassian.net/browse/) +- [PR-299](https://github.com/newrelic/csec-java-agent/pull/299) Support Authentication capabilities for Proxy Settings. [NR-283945](https://new-relic.atlassian.net/browse/NR-283945) +- [PR-313](https://github.com/newrelic/csec-java-agent/pull/313) Processing of the security agent will persist even if the creation of the security home directory encounters an issue. [NR-297206](https://new-relic.atlassian.net/browse/) +- [PR-277](https://github.com/newrelic/csec-java-agent/pull/277) Improve Management of Log file size and its count. [NR-272900](https://new-relic.atlassian.net/browse/) +- [PR-314](https://github.com/newrelic/csec-java-agent/pull/314) Report error to Error Inbox upon connection failure to Security Engine. [NR-299700](https://new-relic.atlassian.net/browse/) +- [PR-316](https://github.com/newrelic/csec-java-agent/pull/316) Detailed IAST Scan metric reporting via HealthCheck. [NR-267166](https://new-relic.atlassian.net/browse/) +- [PR-302](https://github.com/newrelic/csec-java-agent/pull/302) Detect API Endpoint of the Application for Vertx Framework. [NR-287771](https://new-relic.atlassian.net/browse/) +- [PR-293](https://github.com/newrelic/csec-java-agent/pull/293), [PR-284](https://github.com/newrelic/csec-java-agent/pull/284) Detect route of an incoming request for mule server, play framework and Vertx Framework. [NR-283915](https://new-relic.atlassian.net/browse/NR-283915), [NR-265915](https://new-relic.atlassian.net/browse/) + +### Changes +- [PR-277](https://github.com/newrelic/csec-java-agent/pull/277) Improve Secure Cookie event reporting to provide detailed vulnerability. [NR-273609](https://new-relic.atlassian.net/browse/) +- [PR-283](https://github.com/newrelic/csec-java-agent/pull/283) Update IAST Header Parsing Minimum Expected Length Set to 8. [NR-282647](https://new-relic.atlassian.net/browse/) +- [PR-308](https://github.com/newrelic/csec-java-agent/pull/308) Remove jackson-dataformat-properties to address [CVE-2023-3894](https://www.cve.org/CVERecord?id=CVE-2023-3894) and exclude transitive dependency junit to address [CVE-2020-15250](https://www.cve.org/CVERecord?id=CVE-2020-15250) [NR-295033](https://new-relic.atlassian.net/browse/) + +### Fixes +- [PR-292](https://github.com/newrelic/csec-java-agent/pull/292) Fix for ClassNotFoundException observed in glassfish server [NR-262453](https://new-relic.atlassian.net/browse/) +- [PR-286](https://github.com/newrelic/csec-java-agent/pull/286) Detect correct user class in Netty Reactor Server [NR-253551](https://new-relic.atlassian.net/browse/) + ## [1.4.0] - 2024-6-24 ### Changes - Json Version bump to 1.2.3 due to [NR-254157](https://new-relic.atlassian.net/browse/NR-254157) implementation. diff --git a/gradle.properties b/gradle.properties index 4cc8c40f4..9971d5819 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # The agent version. -agentVersion=1.4.0 +agentVersion=1.4.1 jsonVersion=1.2.5 # Updated exposed NR APM API version. nrAPIVersion=8.12.0 From 1064d86576c73d69ad9f94149dcb5b469df366df Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 12 Aug 2024 16:37:30 +0530 Subject: [PATCH 072/122] Send error unsupported agent in error inbox --- .../intcodeagent/controlcommand/ControlCommandProcessor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java index 828eef61b..2fadeaddf 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java @@ -115,6 +115,7 @@ public void run() { case IntCodeControlCommand.UNSUPPORTED_AGENT: logger.log(LogLevel.SEVERE, controlCommand.getArguments().get(0), ControlCommandProcessor.class.getSimpleName()); + NewRelic.noticeError("Incompatible Agent : " + controlCommand.getArguments().get(0), true); System.err.println(controlCommand.getArguments().get(0)); NewRelic.getAgent().getLogger().log(Level.SEVERE, controlCommand.getArguments().get(0)); InstrumentationUtils.shutdownLogic(true); From 4c47c08dd04e42606bebdc8c6955f9d3ea2f9f2e Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 12 Aug 2024 16:54:16 +0530 Subject: [PATCH 073/122] Update jira and PR links in changelogs --- Changelog.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Changelog.md b/Changelog.md index d4b3d9d08..aa1b7a937 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,22 +6,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.4.1] - TBD ### Adds -- [PR-296](https://github.com/newrelic/csec-java-agent/pull/296) Apache Solr Support: The security agent now also supports Apache Solr Version 4.0.0 and above. [NR-288599](https://new-relic.atlassian.net/browse/) -- [PR-275](https://github.com/newrelic/csec-java-agent/pull/275) The maximum permissible size for a request body for scan will be set at 500KB. [NR-174195](https://new-relic.atlassian.net/browse/) -- [PR-306](https://github.com/newrelic/csec-java-agent/pull/306) Add csec prefix to all instrumentation Jar, this resolves CVE flagged by third party scanners on our instrumentation JARs. [NR-289249](https://new-relic.atlassian.net/browse/) -- [PR-303](https://github.com/newrelic/csec-java-agent/pull/303) Honour OFF Flag, Handle Boolean values for config log_level. [NR-293102](https://new-relic.atlassian.net/browse/) +- [PR-296](https://github.com/newrelic/csec-java-agent/pull/296) Apache Solr Support: The security agent now also supports Apache Solr Version 4.0.0 and above. [NR-288599](https://new-relic.atlassian.net/browse/NR-288599) +- [PR-275](https://github.com/newrelic/csec-java-agent/pull/275) The maximum permissible size for a request body for scan will be set at 500KB. [NR-174195](https://new-relic.atlassian.net/browse/NR-174195) +- [PR-306](https://github.com/newrelic/csec-java-agent/pull/306) Add csec prefix to all instrumentation Jar, this resolves CVE flagged by third party scanners on our instrumentation JARs. [NR-289249](https://new-relic.atlassian.net/browse/NR-289249) +- [PR-303](https://github.com/newrelic/csec-java-agent/pull/303) Honour OFF Flag, Handle Boolean values for config log_level. [NR-293102](https://new-relic.atlassian.net/browse/NR-293102) - [PR-299](https://github.com/newrelic/csec-java-agent/pull/299) Support Authentication capabilities for Proxy Settings. [NR-283945](https://new-relic.atlassian.net/browse/NR-283945) -- [PR-313](https://github.com/newrelic/csec-java-agent/pull/313) Processing of the security agent will persist even if the creation of the security home directory encounters an issue. [NR-297206](https://new-relic.atlassian.net/browse/) -- [PR-277](https://github.com/newrelic/csec-java-agent/pull/277) Improve Management of Log file size and its count. [NR-272900](https://new-relic.atlassian.net/browse/) -- [PR-314](https://github.com/newrelic/csec-java-agent/pull/314) Report error to Error Inbox upon connection failure to Security Engine. [NR-299700](https://new-relic.atlassian.net/browse/) -- [PR-316](https://github.com/newrelic/csec-java-agent/pull/316) Detailed IAST Scan metric reporting via HealthCheck. [NR-267166](https://new-relic.atlassian.net/browse/) -- [PR-302](https://github.com/newrelic/csec-java-agent/pull/302) Detect API Endpoint of the Application for Vertx Framework. [NR-287771](https://new-relic.atlassian.net/browse/) -- [PR-293](https://github.com/newrelic/csec-java-agent/pull/293), [PR-284](https://github.com/newrelic/csec-java-agent/pull/284) Detect route of an incoming request for mule server, play framework and Vertx Framework. [NR-283915](https://new-relic.atlassian.net/browse/NR-283915), [NR-265915](https://new-relic.atlassian.net/browse/) +- [PR-313](https://github.com/newrelic/csec-java-agent/pull/313) Processing of the security agent will persist even if the creation of the security home directory encounters an issue. [NR-297206](https://new-relic.atlassian.net/browse/NR-297206) +- [PR-277](https://github.com/newrelic/csec-java-agent/pull/277) Improve Management of Log file size and its count. [NR-272900](https://new-relic.atlassian.net/browse/NR-272900) +- [PR-314](https://github.com/newrelic/csec-java-agent/pull/314) Report error to Error Inbox upon connection failure to Security Engine. [NR-299700](https://new-relic.atlassian.net/browse/NR-299700) +- [PR-316](https://github.com/newrelic/csec-java-agent/pull/316) Detailed IAST Scan metric reporting via HealthCheck. [NR-267166](https://new-relic.atlassian.net/browse/NR-267166) +- [PR-302](https://github.com/newrelic/csec-java-agent/pull/302) Detect API Endpoint of the Application for Vertx Framework. [NR-287771](https://new-relic.atlassian.net/browse/NR-287771) +- [PR-293](https://github.com/newrelic/csec-java-agent/pull/293), [PR-284](https://github.com/newrelic/csec-java-agent/pull/284), [PR-302](https://github.com/newrelic/csec-java-agent/pull/302) Detect route of an incoming request for mule server, play framework and Vertx Framework. [NR-283915](https://new-relic.atlassian.net/browse/NR-283915), [NR-265915](https://new-relic.atlassian.net/browse/), [NR-287771](https://new-relic.atlassian.net/browse/NR-287771) ### Changes -- [PR-277](https://github.com/newrelic/csec-java-agent/pull/277) Improve Secure Cookie event reporting to provide detailed vulnerability. [NR-273609](https://new-relic.atlassian.net/browse/) -- [PR-283](https://github.com/newrelic/csec-java-agent/pull/283) Update IAST Header Parsing Minimum Expected Length Set to 8. [NR-282647](https://new-relic.atlassian.net/browse/) -- [PR-308](https://github.com/newrelic/csec-java-agent/pull/308) Remove jackson-dataformat-properties to address [CVE-2023-3894](https://www.cve.org/CVERecord?id=CVE-2023-3894) and exclude transitive dependency junit to address [CVE-2020-15250](https://www.cve.org/CVERecord?id=CVE-2020-15250) [NR-295033](https://new-relic.atlassian.net/browse/) +- [PR-265](https://github.com/newrelic/csec-java-agent/pull/265) Improve Secure Cookie event reporting to provide detailed vulnerability. [NR-273609](https://new-relic.atlassian.net/browse/NR-273609) +- [PR-283](https://github.com/newrelic/csec-java-agent/pull/283) Update IAST Header Parsing Minimum Expected Length Set to 8. [NR-282647](https://new-relic.atlassian.net/browse/NR-282647) +- [PR-308](https://github.com/newrelic/csec-java-agent/pull/308) Remove jackson-dataformat-properties to address [CVE-2023-3894](https://www.cve.org/CVERecord?id=CVE-2023-3894) and exclude transitive dependency junit to address [CVE-2020-15250](https://www.cve.org/CVERecord?id=CVE-2020-15250) [NR-295033](https://new-relic.atlassian.net/browse/NR-295033) ### Fixes - [PR-292](https://github.com/newrelic/csec-java-agent/pull/292) Fix for ClassNotFoundException observed in glassfish server [NR-262453](https://new-relic.atlassian.net/browse/) From 241c7c1b016da08c56a9241e913a173008606770 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 12 Aug 2024 17:48:03 +0530 Subject: [PATCH 074/122] NR-299709: Workaround for issue #310 Due to CSEC Agent grpc endpoints were breaking in play framework app https://github.com/newrelic/csec-java-agent/issues/310 --- .../server/CsecAkkaHttpContextFunction.scala | 13 ++++++++----- .../http/scaladsl/AkkaAsyncRequestHandler.scala | 13 ++++++++----- .../akka/http/scaladsl/AkkaSyncRequestHandler.scala | 13 ++++++++----- .../http/scaladsl/AkkaAsyncRequestHandler.scala | 12 +++++++----- .../akka/http/scaladsl/AkkaSyncRequestHandler.scala | 12 +++++++----- .../http/scaladsl/AkkaAsyncRequestHandler.scala | 12 +++++++----- .../akka/http/scaladsl/AkkaSyncRequestHandler.scala | 12 +++++++----- .../http/scaladsl/AkkaAsyncRequestHandler.scala | 13 ++++++++----- .../akka/http/scaladsl/AkkaSyncRequestHandler.scala | 13 ++++++++----- 9 files changed, 68 insertions(+), 45 deletions(-) diff --git a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/CsecAkkaHttpContextFunction.scala b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/CsecAkkaHttpContextFunction.scala index 4a974e768..2ebd36c77 100644 --- a/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/CsecAkkaHttpContextFunction.scala +++ b/instrumentation-security/akka-http-2.11_10.0.0/src/main/scala/akka/http/scaladsl/server/CsecAkkaHttpContextFunction.scala @@ -8,6 +8,7 @@ package akka.http.scaladsl.server import akka.Done +import akka.http.scaladsl.model.HttpEntity import akka.stream.javadsl.Source import akka.stream.scaladsl.Sink import akka.util.ByteString @@ -55,15 +56,17 @@ class CsecContextWrapper(original: Function1[RequestContext, Future[RouteResult] override def apply(ctx: RequestContext): Future[RouteResult] = { try { - var httpRequest = ctx.request; + val httpRequest = ctx.request; val body: lang.StringBuilder = new lang.StringBuilder(); val dataBytes: Source[ByteString, AnyRef] = httpRequest.entity.getDataBytes() val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible(); - val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => - val chunk = byteString.utf8String - body.append(chunk) + if (!httpRequest.entity.isInstanceOf[HttpEntity.Chunked]) { + val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => + val chunk = byteString.utf8String + body.append(chunk) + } + val processingResult: Future[Done] = dataBytes.runWith(sink, ctx.materializer) } - val processingResult: Future[Done] = dataBytes.runWith(sink, ctx.materializer) AkkaCoreUtils.preProcessHttpRequest(isLockAquired, httpRequest, body, NewRelic.getAgent.getTransaction.getToken); original.apply(ctx) } catch { diff --git a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala index f1d3534c5..76bef8435 100644 --- a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala +++ b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala @@ -8,7 +8,7 @@ package akka.http.scaladsl import akka.Done -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} +import akka.http.scaladsl.model.{HttpEntity, HttpRequest, HttpResponse} import akka.stream.Materializer import akka.stream.javadsl.Source import akka.stream.scaladsl.Sink @@ -26,11 +26,14 @@ class AkkaAsyncRequestHandler(handler: HttpRequest ⇒ Future[HttpResponse])(imp val body: lang.StringBuilder = new lang.StringBuilder(); val dataBytes: Source[ByteString, AnyRef] = param.entity.getDataBytes() val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible(); - val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => - val chunk = byteString.utf8String - body.append(chunk) + if (!param.entity.isInstanceOf[HttpEntity.Chunked]) { + val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => + val chunk = byteString.utf8String + body.append(chunk) + } + val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) } - val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) + AkkaCoreUtils.preProcessHttpRequest(isLockAquired, param, body, NewRelic.getAgent.getTransaction.getToken); val futureResponse: Future[HttpResponse] = handler.apply(param) futureResponse.flatMap(ResponseFutureHelper.wrapResponseAsync(NewRelic.getAgent.getTransaction.getToken, materializer)) diff --git a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala index 18dbe8b67..bb1f64a44 100644 --- a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala +++ b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala @@ -8,7 +8,7 @@ package akka.http.scaladsl import akka.Done -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} +import akka.http.scaladsl.model.{HttpEntity, HttpRequest, HttpResponse} import akka.stream.Materializer import akka.stream.javadsl.Source import akka.stream.scaladsl.Sink @@ -26,11 +26,14 @@ class AkkaSyncRequestHandler(handler: HttpRequest ⇒ HttpResponse)(implicit mat val body: lang.StringBuilder = new lang.StringBuilder(); val dataBytes: Source[ByteString, AnyRef] = param.entity.getDataBytes() val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible(); - val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => - val chunk = byteString.utf8String - body.append(chunk) + + if (!param.entity.isInstanceOf[HttpEntity.Chunked]) { + val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => + val chunk = byteString.utf8String + body.append(chunk) + } + val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) } - val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) AkkaCoreUtils.preProcessHttpRequest(isLockAquired, param, body, NewRelic.getAgent.getTransaction.getToken); val response: HttpResponse = handler.apply(param) ResponseFutureHelper.wrapResponseSync(response, materializer) diff --git a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala index f1d3534c5..d6d0370cd 100644 --- a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala +++ b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala @@ -8,7 +8,7 @@ package akka.http.scaladsl import akka.Done -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} +import akka.http.scaladsl.model.{HttpEntity, HttpRequest, HttpResponse} import akka.stream.Materializer import akka.stream.javadsl.Source import akka.stream.scaladsl.Sink @@ -26,11 +26,13 @@ class AkkaAsyncRequestHandler(handler: HttpRequest ⇒ Future[HttpResponse])(imp val body: lang.StringBuilder = new lang.StringBuilder(); val dataBytes: Source[ByteString, AnyRef] = param.entity.getDataBytes() val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible(); - val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => - val chunk = byteString.utf8String - body.append(chunk) + if (!param.entity.isInstanceOf[HttpEntity.Chunked]) { + val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => + val chunk = byteString.utf8String + body.append(chunk) + } + val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) } - val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) AkkaCoreUtils.preProcessHttpRequest(isLockAquired, param, body, NewRelic.getAgent.getTransaction.getToken); val futureResponse: Future[HttpResponse] = handler.apply(param) futureResponse.flatMap(ResponseFutureHelper.wrapResponseAsync(NewRelic.getAgent.getTransaction.getToken, materializer)) diff --git a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala index 18dbe8b67..f8b63323c 100644 --- a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala +++ b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala @@ -8,7 +8,7 @@ package akka.http.scaladsl import akka.Done -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} +import akka.http.scaladsl.model.{HttpEntity, HttpRequest, HttpResponse} import akka.stream.Materializer import akka.stream.javadsl.Source import akka.stream.scaladsl.Sink @@ -26,11 +26,13 @@ class AkkaSyncRequestHandler(handler: HttpRequest ⇒ HttpResponse)(implicit mat val body: lang.StringBuilder = new lang.StringBuilder(); val dataBytes: Source[ByteString, AnyRef] = param.entity.getDataBytes() val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible(); - val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => - val chunk = byteString.utf8String - body.append(chunk) + if (!param.entity.isInstanceOf[HttpEntity.Chunked]) { + val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => + val chunk = byteString.utf8String + body.append(chunk) + } + val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) } - val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) AkkaCoreUtils.preProcessHttpRequest(isLockAquired, param, body, NewRelic.getAgent.getTransaction.getToken); val response: HttpResponse = handler.apply(param) ResponseFutureHelper.wrapResponseSync(response, materializer) diff --git a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala index f1d3534c5..d6d0370cd 100644 --- a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala +++ b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala @@ -8,7 +8,7 @@ package akka.http.scaladsl import akka.Done -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} +import akka.http.scaladsl.model.{HttpEntity, HttpRequest, HttpResponse} import akka.stream.Materializer import akka.stream.javadsl.Source import akka.stream.scaladsl.Sink @@ -26,11 +26,13 @@ class AkkaAsyncRequestHandler(handler: HttpRequest ⇒ Future[HttpResponse])(imp val body: lang.StringBuilder = new lang.StringBuilder(); val dataBytes: Source[ByteString, AnyRef] = param.entity.getDataBytes() val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible(); - val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => - val chunk = byteString.utf8String - body.append(chunk) + if (!param.entity.isInstanceOf[HttpEntity.Chunked]) { + val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => + val chunk = byteString.utf8String + body.append(chunk) + } + val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) } - val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) AkkaCoreUtils.preProcessHttpRequest(isLockAquired, param, body, NewRelic.getAgent.getTransaction.getToken); val futureResponse: Future[HttpResponse] = handler.apply(param) futureResponse.flatMap(ResponseFutureHelper.wrapResponseAsync(NewRelic.getAgent.getTransaction.getToken, materializer)) diff --git a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala index 18dbe8b67..f8b63323c 100644 --- a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala +++ b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala @@ -8,7 +8,7 @@ package akka.http.scaladsl import akka.Done -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} +import akka.http.scaladsl.model.{HttpEntity, HttpRequest, HttpResponse} import akka.stream.Materializer import akka.stream.javadsl.Source import akka.stream.scaladsl.Sink @@ -26,11 +26,13 @@ class AkkaSyncRequestHandler(handler: HttpRequest ⇒ HttpResponse)(implicit mat val body: lang.StringBuilder = new lang.StringBuilder(); val dataBytes: Source[ByteString, AnyRef] = param.entity.getDataBytes() val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible(); - val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => - val chunk = byteString.utf8String - body.append(chunk) + if (!param.entity.isInstanceOf[HttpEntity.Chunked]) { + val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => + val chunk = byteString.utf8String + body.append(chunk) + } + val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) } - val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) AkkaCoreUtils.preProcessHttpRequest(isLockAquired, param, body, NewRelic.getAgent.getTransaction.getToken); val response: HttpResponse = handler.apply(param) ResponseFutureHelper.wrapResponseSync(response, materializer) diff --git a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala index e73c15e44..922fe6070 100644 --- a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala +++ b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaAsyncRequestHandler.scala @@ -8,7 +8,7 @@ package akka.http.scaladsl import akka.Done -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} +import akka.http.scaladsl.model.{HttpEntity, HttpRequest, HttpResponse} import akka.stream.Materializer import akka.stream.javadsl.Source import akka.stream.scaladsl.Sink @@ -26,11 +26,14 @@ class AkkaAsyncRequestHandler(handler: HttpRequest ⇒ Future[HttpResponse])(imp val body: lang.StringBuilder = new lang.StringBuilder(); val dataBytes: Source[ByteString, AnyRef] = param.entity.getDataBytes() val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible(); - val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => - val chunk = byteString.utf8String - body.append(chunk) + + if (!param.entity.isInstanceOf[HttpEntity.Chunked]) { + val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => + val chunk = byteString.utf8String + body.append(chunk) + } + val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) } - val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) AkkaCoreUtils.preProcessHttpRequest(isLockAquired, param, body, NewRelic.getAgent.getTransaction.getToken); val futureResponse: Future[HttpResponse] = handler.apply(param) futureResponse.flatMap(ResponseFutureHelper.wrapResponseAsync(NewRelic.getAgent.getTransaction.getToken, materializer)) diff --git a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala index 6e3cbf634..d0f99f329 100644 --- a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala +++ b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/AkkaSyncRequestHandler.scala @@ -8,7 +8,7 @@ package akka.http.scaladsl import akka.Done -import akka.http.scaladsl.model.{HttpRequest, HttpResponse} +import akka.http.scaladsl.model.{HttpEntity, HttpRequest, HttpResponse} import akka.stream.Materializer import akka.stream.javadsl.Source import akka.stream.scaladsl.Sink @@ -27,11 +27,14 @@ class AkkaSyncRequestHandler(handler: HttpRequest ⇒ HttpResponse)(implicit mat val body: lang.StringBuilder = new lang.StringBuilder(); val dataBytes: Source[ByteString, AnyRef] = param.entity.getDataBytes() val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible(); - val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => - val chunk = byteString.utf8String - body.append(chunk) + + if (!param.entity.isInstanceOf[HttpEntity.Chunked]) { + val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString => + val chunk = byteString.utf8String + body.append(chunk) + } + val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) } - val processingResult: Future[Done] = dataBytes.runWith(sink, materializer) AkkaCoreUtils.preProcessHttpRequest(isLockAquired, param, body, NewRelic.getAgent.getTransaction.getToken); val response: HttpResponse = handler.apply(param) ResponseFutureHelper.wrapResponseSync(response, materializer) From e5678827874d5644a10ceb24b094c1c53e70a7eb Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 12 Aug 2024 17:58:36 +0530 Subject: [PATCH 075/122] Update jira and PR links in changelogs --- Changelog.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index aa1b7a937..4599818e6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-314](https://github.com/newrelic/csec-java-agent/pull/314) Report error to Error Inbox upon connection failure to Security Engine. [NR-299700](https://new-relic.atlassian.net/browse/NR-299700) - [PR-316](https://github.com/newrelic/csec-java-agent/pull/316) Detailed IAST Scan metric reporting via HealthCheck. [NR-267166](https://new-relic.atlassian.net/browse/NR-267166) - [PR-302](https://github.com/newrelic/csec-java-agent/pull/302) Detect API Endpoint of the Application for Vertx Framework. [NR-287771](https://new-relic.atlassian.net/browse/NR-287771) -- [PR-293](https://github.com/newrelic/csec-java-agent/pull/293), [PR-284](https://github.com/newrelic/csec-java-agent/pull/284), [PR-302](https://github.com/newrelic/csec-java-agent/pull/302) Detect route of an incoming request for mule server, play framework and Vertx Framework. [NR-283915](https://new-relic.atlassian.net/browse/NR-283915), [NR-265915](https://new-relic.atlassian.net/browse/), [NR-287771](https://new-relic.atlassian.net/browse/NR-287771) +- [PR-293](https://github.com/newrelic/csec-java-agent/pull/293), [PR-284](https://github.com/newrelic/csec-java-agent/pull/284), [PR-302](https://github.com/newrelic/csec-java-agent/pull/302) Detect route of an incoming request for mule server, play framework and Vertx Framework. [NR-283915](https://new-relic.atlassian.net/browse/NR-283915), [NR-265915](https://new-relic.atlassian.net/browse/NR-265915), [NR-287771](https://new-relic.atlassian.net/browse/NR-287771) ### Changes - [PR-265](https://github.com/newrelic/csec-java-agent/pull/265) Improve Secure Cookie event reporting to provide detailed vulnerability. [NR-273609](https://new-relic.atlassian.net/browse/NR-273609) @@ -24,8 +24,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-308](https://github.com/newrelic/csec-java-agent/pull/308) Remove jackson-dataformat-properties to address [CVE-2023-3894](https://www.cve.org/CVERecord?id=CVE-2023-3894) and exclude transitive dependency junit to address [CVE-2020-15250](https://www.cve.org/CVERecord?id=CVE-2020-15250) [NR-295033](https://new-relic.atlassian.net/browse/NR-295033) ### Fixes -- [PR-292](https://github.com/newrelic/csec-java-agent/pull/292) Fix for ClassNotFoundException observed in glassfish server [NR-262453](https://new-relic.atlassian.net/browse/) -- [PR-286](https://github.com/newrelic/csec-java-agent/pull/286) Detect correct user class in Netty Reactor Server [NR-253551](https://new-relic.atlassian.net/browse/) +- [PR-292](https://github.com/newrelic/csec-java-agent/pull/292) Fix for ClassNotFoundException observed in glassfish server [NR-262453](https://new-relic.atlassian.net/browse/NR-262453) +- [PR-286](https://github.com/newrelic/csec-java-agent/pull/286) Detect correct user class in Netty Reactor Server [NR-253551](https://new-relic.atlassian.net/browse/NR-253551) ## [1.4.0] - 2024-6-24 ### Changes @@ -40,7 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-126](https://github.com/newrelic/csec-java-agent/pull/126), [PR-127](https://github.com/newrelic/csec-java-agent/pull/127), [PR-128](https://github.com/newrelic/csec-java-agent/pull/128), [PR-129](https://github.com/newrelic/csec-java-agent/pull/129) Jedis Support : The security agent now also supports Jedis Version 1.4.0 and above. [NR-174176](https://new-relic.atlassian.net/browse/NR-174176) - [PR-287](https://github.com/newrelic/csec-java-agent/pull/287) Support for Proxy Settings for Connecting to the Security Engine, with known limitation of missing Authentication capabilities. ### Fixes -- [PR-255](https://github.com/newrelic/csec-java-agent/pull/255) Handle InvalidPathException thrown by Paths.get method [NR-262452](https://new-relic.atlassian.net/browse/) +- [PR-255](https://github.com/newrelic/csec-java-agent/pull/255) Handle InvalidPathException thrown by Paths.get method [NR-262452](https://new-relic.atlassian.net/browse/NR-262452) - [PR-216](https://github.com/newrelic/csec-java-agent/pull/216) Extract Server Configuration to resolve IAST localhost connection with application for Glassfish Server. [NR-223808](https://new-relic.atlassian.net/browse/NR-223808) - [PR-214](https://github.com/newrelic/csec-java-agent/pull/214) Extract Server Configuration to resolve IAST localhost connection with application for Weblogic Server. [NR-223809](https://new-relic.atlassian.net/browse/NR-223809) - [PR-242](https://github.com/newrelic/csec-java-agent/pull/242) Fix for User Class detection in Play Framework [NR-264101](https://new-relic.atlassian.net/browse/NR-264101) From d1b1e78701853728a946717011d948f8fd23eb29 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 12 Aug 2024 18:09:42 +0530 Subject: [PATCH 076/122] Disabling UTs and instrumentation-verifier run when publishing to maven repo to Avoid Github Action Job Stuck Issues --- .github/workflows/publish-release-to-maven.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-release-to-maven.yml b/.github/workflows/publish-release-to-maven.yml index 3a2deecbf..1aae7301b 100644 --- a/.github/workflows/publish-release-to-maven.yml +++ b/.github/workflows/publish-release-to-maven.yml @@ -12,8 +12,8 @@ jobs: with: apm-repo: 'k2io/newrelic-java-agent' apm-source-ref: 'csec-dev' - csec-run-unittest: 'true' - csec-run-instrumentation-verify: 'true' + csec-run-unittest: 'false' + csec-run-instrumentation-verify: 'false' is-release: 'true' version-suffix: '' slack-notify: 'true' \ No newline at end of file From 4d2ad14ab0493e1173cb4153121abdddc18398f3 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 13 Aug 2024 10:54:28 +0530 Subject: [PATCH 077/122] Send error in Error Inbox, when SA is unable to generate CA Certs --- .../intcodeagent/controlcommand/ControlCommandProcessor.java | 2 +- .../agent/security/intcodeagent/websocket/WSClient.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java index 2fadeaddf..293943e48 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java @@ -115,7 +115,7 @@ public void run() { case IntCodeControlCommand.UNSUPPORTED_AGENT: logger.log(LogLevel.SEVERE, controlCommand.getArguments().get(0), ControlCommandProcessor.class.getSimpleName()); - NewRelic.noticeError("Incompatible Agent : " + controlCommand.getArguments().get(0), true); + NewRelic.noticeError("Incompatible New Relic Security Agent: " + controlCommand.getArguments().get(0), true); System.err.println(controlCommand.getArguments().get(0)); NewRelic.getAgent().getLogger().log(Level.SEVERE, controlCommand.getArguments().get(0)); InstrumentationUtils.shutdownLogic(true); 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 8f24f3f8b..29477b006 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 @@ -89,6 +89,7 @@ private SSLContext createSSLContext() throws Exception { } catch (Exception e) { logger.log(LogLevel.SEVERE, "Unable to generate ca certificate. Verify the certificate format. Will not process further certs.", e, WSClient.class.getName()); + NewRelic.noticeError("New Relic Security Agent is unable to generate CA Certificate. Verify the certificate format. Will not process further certs.", true); break; } } From 7431b174f916d512363527e17dba403deea99d73 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 13 Aug 2024 10:59:12 +0530 Subject: [PATCH 078/122] Send error in Error Inbox, when SA is unable to generate CA Certs --- .../agent/security/intcodeagent/websocket/WSClient.java | 2 +- 1 file changed, 1 insertion(+), 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 29477b006..338fb464d 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 @@ -89,7 +89,7 @@ private SSLContext createSSLContext() throws Exception { } catch (Exception e) { logger.log(LogLevel.SEVERE, "Unable to generate ca certificate. Verify the certificate format. Will not process further certs.", e, WSClient.class.getName()); - NewRelic.noticeError("New Relic Security Agent is unable to generate CA Certificate. Verify the certificate format. Will not process further certs.", true); + NewRelic.noticeError(new SecurityNoticeError("New Relic Security Agent is unable to generate CA Certificate. Verify the certificate format. Will not process further certs.", e), noticeErrorCustomParameters, true); break; } } From cbf463eefb6dadc4efc73be3a51832d6a7d555cd Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 13 Aug 2024 11:17:12 +0530 Subject: [PATCH 079/122] Fix for NPE in snapshot dir --- .../src/main/java/com/newrelic/agent/security/AgentConfig.java | 3 +++ .../agent/security/instrumentator/os/OsVariablesInstance.java | 2 +- .../intcodeagent/logging/HealthCheckScheduleThread.java | 3 +++ 3 files changed, 7 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 d2216244e..b04552634 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 @@ -177,6 +177,9 @@ public void setConfig(CollectorConfig config) { } public void createSnapshotDirectory() throws IOException { + if (osVariables.getSnapshotDir() == null){ + return; + } Path snapshotDir = Paths.get(osVariables.getSnapshotDir()); // Remove any file with this name from target. if (!snapshotDir.toFile().isDirectory()) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java index 1e8d5c30f..86964a2a6 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/os/OsVariablesInstance.java @@ -29,8 +29,8 @@ private OsVariablesInstance() { if(StringUtils.isNotBlank(AgentConfig.getInstance().getSecurityHome())) { osVariables.setLogDirectory(Paths.get(AgentConfig.getInstance().getSecurityHome(), LOGS).toString()); osVariables.setTmpDirectory(Paths.get(AgentConfig.getInstance().getSecurityHome(), TMP, LANGUAGE_AGENT, AgentInfo.getInstance().getApplicationUUID()).toString()); + osVariables.setSnapshotDir(Paths.get(osVariables.getLogDirectory(), SNAPSHOTS).toString()); } - osVariables.setSnapshotDir(Paths.get(osVariables.getLogDirectory(), SNAPSHOTS).toString()); // osVariables.setPolicyConfigPath(Paths.get(k2root.toString(), CONFIG, LANGUAGE_AGENT).toString()); if (SystemUtils.IS_OS_LINUX) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java index 71208cc35..308d513da 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/HealthCheckScheduleThread.java @@ -142,6 +142,9 @@ private void writeStatusLogFile(JAHealthCheck sendJaHealthCheck) { if(writerHealthCheck == null){ writerHealthCheck = AgentInfo.getInstance().getJaHealthCheck(); } + if (osVariables.getSnapshotDir() == null){ + return; + } File statusLog = new File(osVariables.getSnapshotDir(), String.format(K_2_AGENT_STATUS_LOG, AgentInfo.getInstance().getApplicationUUID())); try { FileUtils.deleteQuietly(statusLog); From c8cc5dd25f29eb93b2215d65aa861acf920d1e88 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 13 Aug 2024 11:18:46 +0530 Subject: [PATCH 080/122] Update changelogs for deprecations --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index 4599818e6..52f2c7869 100644 --- a/Changelog.md +++ b/Changelog.md @@ -27,6 +27,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-292](https://github.com/newrelic/csec-java-agent/pull/292) Fix for ClassNotFoundException observed in glassfish server [NR-262453](https://new-relic.atlassian.net/browse/NR-262453) - [PR-286](https://github.com/newrelic/csec-java-agent/pull/286) Detect correct user class in Netty Reactor Server [NR-253551](https://new-relic.atlassian.net/browse/NR-253551) +### Deprecations +- Status File Used for Debugging: This feature has been deprecated. All debugging capabilities have been moved to either Init Logging or [Error Inbox](https://docs.newrelic.com/docs/errors-inbox/errors-inbox/) and will be removed in a future agent release. [NR-293966](https://new-relic.atlassian.net/browse/NR-293966) + ## [1.4.0] - 2024-6-24 ### Changes - Json Version bump to 1.2.3 due to [NR-254157](https://new-relic.atlassian.net/browse/NR-254157) implementation. From b44d760c3f2b7c96c74b3598a8de5abd1f52890e Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 13 Aug 2024 11:25:54 +0530 Subject: [PATCH 081/122] Fix for NPE in AgentConfig --- .../main/java/com/newrelic/agent/security/AgentConfig.java | 4 +++- 1 file changed, 3 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 b04552634..84bda35e3 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 @@ -44,7 +44,7 @@ public class AgentConfig { private boolean isNRSecurityEnabled; - private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); + private static FileLoggerThreadPool logger; private OSVariables osVariables; @@ -64,6 +64,8 @@ public void instantiate(){ groupName = applyRequiredGroup(); //Instantiation call please do not move or repeat this. osVariables = OsVariablesInstance.instantiate().getOsVariables(); + + logger = FileLoggerThreadPool.getInstance(); // Set required LogLevel logLevel = applyRequiredLogLevel(); } From 73389177647f3ced030e7153648085ec3c1c0aec Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 13 Aug 2024 12:41:06 +0530 Subject: [PATCH 082/122] update for route detection in case of empty endpoints --- .../com/newrelic/api/agent/security/Agent.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 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 535aa27b5..a01daf2f5 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 @@ -323,16 +323,18 @@ public void registerOperation(AbstractOperation operation) { // boolean blockNeeded = checkIfBlockingNeeded(operation.getApiID()); // securityMetaData.getMetaData().setApiBlocked(blockNeeded); HttpRequest request = securityMetaData.getRequest(); -// if (StringUtils.isEmpty(request.getRoute())){ Framework frameWork = Framework.UNKNOWN; if(!securityMetaData.getFuzzRequestIdentifier().getK2Request() && StringUtils.isNotBlank(securityMetaData.getMetaData().getFramework())) { frameWork = Framework.valueOf(securityMetaData.getMetaData().getFramework()); } if (!securityMetaData.getFuzzRequestIdentifier().getK2Request() && StringUtils.isEmpty(request.getRoute())){ - request.setRoute(getEndpointRoute(StringUtils.substringBefore(request.getUrl(), "?"), frameWork), true); - logger.log(LogLevel.FINEST,"Route detection using Application Endpoint", this.getClass().getName()); + String route = getEndpointRoute(StringUtils.substringBefore(request.getUrl(), "?"), frameWork); + if (route != null) { + request.setRoute(route); + logger.log(LogLevel.FINEST,"Route detection using Application Endpoint", this.getClass().getName()); + } } -// } + if (needToGenerateEvent(operation.getApiID())) { DispatcherPool.getInstance().dispatchEvent(operation, securityMetaData); if (!firstEventProcessed.get()) { @@ -358,7 +360,7 @@ private String getEndpointRoute(String uri, Framework framework){ private String getEndpointRoute(String uri) { List uriSegments = URLMappingsHelper.getSegments(uri); if (uriSegments.isEmpty()){ - return StringUtils.EMPTY; + return null; } for (RouteSegments routeSegments : URLMappingsHelper.getRouteSegments()) { int uriSegIdx = 0; @@ -384,7 +386,7 @@ private String getEndpointRoute(String uri) { } } } - return StringUtils.EMPTY; + return null; } private int jumpRoute(List value, int i1, List uriSegments, int i) { From 1a6f4d4050eb7b008a84f10111f0d4fd11c612d2 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 13 Aug 2024 13:32:45 +0530 Subject: [PATCH 083/122] Update changelogs --- Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index 52f2c7869..58f975a07 100644 --- a/Changelog.md +++ b/Changelog.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixes - [PR-292](https://github.com/newrelic/csec-java-agent/pull/292) Fix for ClassNotFoundException observed in glassfish server [NR-262453](https://new-relic.atlassian.net/browse/NR-262453) - [PR-286](https://github.com/newrelic/csec-java-agent/pull/286) Detect correct user class in Netty Reactor Server [NR-253551](https://new-relic.atlassian.net/browse/NR-253551) +- [PR-317](https://github.com/newrelic/csec-java-agent/pull/317) Add a workaround for an issue where New Relic Security Agent breaks the gRPC endpoints [#130](https://github.com/newrelic/csec-java-agent/issues/310). [NR-299709](https://new-relic.atlassian.net/browse/NR-299709) ### Deprecations - Status File Used for Debugging: This feature has been deprecated. All debugging capabilities have been moved to either Init Logging or [Error Inbox](https://docs.newrelic.com/docs/errors-inbox/errors-inbox/) and will be removed in a future agent release. [NR-293966](https://new-relic.atlassian.net/browse/NR-293966) @@ -42,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [PR-256](https://github.com/newrelic/csec-java-agent/pull/256), [PR-259](https://github.com/newrelic/csec-java-agent/pull/259), [PR-258](https://github.com/newrelic/csec-java-agent/pull/258) Feature to detect route of an incoming request for Jax-RS and Spring Framework. [NR-265913](https://new-relic.atlassian.net/browse/NR-265913), [NR-261653](https://new-relic.atlassian.net/browse/NR-261653), [NR-273605](https://new-relic.atlassian.net/browse/NR-273605) - [PR-126](https://github.com/newrelic/csec-java-agent/pull/126), [PR-127](https://github.com/newrelic/csec-java-agent/pull/127), [PR-128](https://github.com/newrelic/csec-java-agent/pull/128), [PR-129](https://github.com/newrelic/csec-java-agent/pull/129) Jedis Support : The security agent now also supports Jedis Version 1.4.0 and above. [NR-174176](https://new-relic.atlassian.net/browse/NR-174176) - [PR-287](https://github.com/newrelic/csec-java-agent/pull/287) Support for Proxy Settings for Connecting to the Security Engine, with known limitation of missing Authentication capabilities. + ### Fixes - [PR-255](https://github.com/newrelic/csec-java-agent/pull/255) Handle InvalidPathException thrown by Paths.get method [NR-262452](https://new-relic.atlassian.net/browse/NR-262452) - [PR-216](https://github.com/newrelic/csec-java-agent/pull/216) Extract Server Configuration to resolve IAST localhost connection with application for Glassfish Server. [NR-223808](https://new-relic.atlassian.net/browse/NR-223808) From 9ecfd771144fdd8864d1987371f6072a5c2fa7f0 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 14 Aug 2024 10:54:47 +0530 Subject: [PATCH 084/122] Adds Configuration for IAST_SCHEDULE and IAST_SCAN_IGNORE feature Implements IAST_SCHEDULE --- .../newrelic/agent/security/AgentConfig.java | 87 ++++++--- .../instrumentator/dispatcher/Dispatcher.java | 4 +- .../ControlCommandProcessor.java | 7 + .../models/collectorconfig/AgentMode.java | 24 +++ .../utils/RestrictionUtility.java | 23 +++ .../intcodeagent/websocket/WSClient.java | 1 + .../agent/security/util/IUtilConstants.java | 23 ++- .../newrelic/api/agent/security/Agent.java | 34 +++- .../newrelic/api/agent/security/Agent.java | 7 + .../api/agent/security/NoOpAgent.java | 7 + .../api/agent/security/SecurityAgent.java | 3 + .../instrumentation/helpers/FileHelper.java | 2 +- .../helpers/GenericHelper.java | 67 +++++++ .../instrumentation/helpers/JdbcHelper.java | 8 +- .../instrumentation/helpers/R2dbcHelper.java | 18 +- .../schema/policy/IastDetectionCategory.java | 167 ++++++++++++++++++ .../schema/policy/RestrictionCriteria.java | 10 +- .../{ScanTime.java => ScanSchedule.java} | 16 +- .../security/schema/policy/SkipScan.java | 55 ++++++ 19 files changed, 497 insertions(+), 66 deletions(-) create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java rename newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/{ScanTime.java => ScanSchedule.java} (71%) create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScan.java 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 f92150994..8aa440320 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 @@ -1,7 +1,5 @@ package com.newrelic.agent.security; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.newrelic.agent.security.instrumentator.os.OSVariables; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.instrumentator.utils.AgentUtils; @@ -30,6 +28,7 @@ import java.text.ParseException; import java.time.Instant; import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import static com.newrelic.agent.security.util.IUtilConstants.*; @@ -40,12 +39,13 @@ public class AgentConfig { public static final String AGENT_JAR_LOCATION = "agent_jar_location"; public static final String AGENT_HOME = "agent_home"; - public static final String INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE = "Invalid cron expression provided for IAST Restricted Mode"; + public static final String INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE = "Invalid cron expression provided for IAST Mode"; public static final String ACCOUNT_ID_IS_REQUIRED_FOR_IAST_RESTRICTED_MODE = "Account ID is required for IAST Restricted Mode"; public static final String ACCOUNT_ID_LOCATION = "account_id_location"; public static final String ACCOUNT_ID_KEY = "account_id_key"; public static final String ROUTE = "route"; public static final String MAPPING_PARAMETERS_ARE_REQUIRED_FOR_IAST_RESTRICTED_MODE = "Mapping Parameters are required for IAST Restricted Mode"; + public static final String DEFAULT_SCAN_SCHEDULE_EXPRESSION = "0 0 0 * * ?"; private String NR_CSEC_HOME; private String logLevel; @@ -88,15 +88,14 @@ public long instantiate(){ instantiateAgentMode(groupName); - return trigerIAST(); + return triggerIAST(); } - public long trigerIAST() { + public long triggerIAST() { try { - if(agentMode.getIastScan().getEnabled() && agentMode.getIastScan().getRestricted()){ - long date = agentMode.getIastScan().getRestrictionCriteria().getScanTime().getNextScanTime().getTime(); - long currentTime = Instant.now().toEpochMilli(); - return date-currentTime; + if(agentMode.getScanSchedule().getNextScanTime() != null) { + logger.log(LogLevel.FINER, "Security Agent scan time is set to : " + agentMode.getScanSchedule().getNextScanTime(), AgentConfig.class.getName()); + return agentMode.getScanSchedule().getNextScanTime().getTime() - Instant.now().toEpochMilli(); } } catch (Exception e){ NewRelic.noticeError(new RestrictionModeException("Error while calculating next scan time for IAST Restricted Mode", e), Agent.getCustomNoticeErrorParameters(), true); @@ -132,16 +131,63 @@ private void instantiateAgentMode(String groupName) { break; } + try { + readScanSchedule(); + } catch (RestrictionModeException e){ + System.err.println("[NR-CSEC-JA] Error while reading Scan Schedule Configuration. Security will be disabled."); + NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading Scan Schedule Configuration. Security will be disabled."); + NewRelic.noticeError(e, Agent.getCustomNoticeErrorParameters(), true); + AgentInfo.getInstance().agentStatTrigger(false); + } + readSkipScan(); + + } + + private void readSkipScan() { + agentMode.getSkipScan().setApis(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_API, Collections.emptyList())); + agentMode.getSkipScan().getParameters().setQuery(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_QUERY, Collections.emptyList())); + agentMode.getSkipScan().getParameters().setHeader(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_HEADER, Collections.emptyList())); + agentMode.getSkipScan().getParameters().setBody(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_BODY, Collections.emptyList())); + agentMode.getSkipScan().getIastDetectionCategory().setInsecureSettingsEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INSECURE_SETTINGS, true)); + agentMode.getSkipScan().getIastDetectionCategory().setInvalidFileAccessEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INVALID_FILE_ACCESS, true)); + agentMode.getSkipScan().getIastDetectionCategory().setSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SQL_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setNoSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_NOSQL_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setLdapInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_LDAP_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setJavascriptInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_JAVASCRIPT_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setCommandInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_COMMAND_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setXpathInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_XPATH_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setSsrfEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SSRF, true)); + agentMode.getSkipScan().getIastDetectionCategory().setRxssEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_RXSS, true)); + agentMode.getSkipScan().getIastDetectionCategory().generateDisabledCategoriesCSV(); + } + + private void readScanSchedule() throws RestrictionModeException { + agentMode.getScanSchedule().setDelay(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_DELAY, 0)); + agentMode.getScanSchedule().setDuration(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_DURATION, 0)); + agentMode.getScanSchedule().setSchedule(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_SCHEDULE, StringUtils.EMPTY)); + if(agentMode.getScanSchedule().getDelay() > 0) { + agentMode.getScanSchedule().setNextScanTime(new Date(Instant.now().toEpochMilli() + TimeUnit.MINUTES.toMillis(agentMode.getScanSchedule().getDelay()))); + } else if(StringUtils.isNotBlank(agentMode.getScanSchedule().getSchedule())) { + if(CronExpression.isValidExpression(agentMode.getScanSchedule().getSchedule())){ + try { + agentMode.getScanSchedule().setNextScanTime(new CronExpression(agentMode.getScanSchedule().getSchedule()).getTimeAfter(new Date())); + } catch (ParseException e) { + throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE, e); + } + } else { + throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE); + } + } } private void updateSkipScanParameters() { for (MappingParameters mappingParameter : this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters()) { if(mappingParameter.getAccountIdLocation().equals(HttpParameterLocation.HEADER)){ - this.agentMode.getIastScan().getRestrictionCriteria().getSkipScanParameters().getHeader().add(mappingParameter.getAccountIdKey()); + this.agentMode.getSkipScan().getParameters().getHeader().add(mappingParameter.getAccountIdKey()); } else if(mappingParameter.getAccountIdLocation().equals(HttpParameterLocation.QUERY)){ - this.agentMode.getIastScan().getRestrictionCriteria().getSkipScanParameters().getQuery().add(mappingParameter.getAccountIdKey()); + this.agentMode.getSkipScan().getParameters().getQuery().add(mappingParameter.getAccountIdKey()); } else if(mappingParameter.getAccountIdLocation().equals(HttpParameterLocation.BODY)){ - this.agentMode.getIastScan().getRestrictionCriteria().getSkipScanParameters().getBody().add(mappingParameter.getAccountIdKey()); + this.agentMode.getSkipScan().getParameters().getBody().add(mappingParameter.getAccountIdKey()); } } } @@ -149,6 +195,7 @@ private void updateSkipScanParameters() { private void readIastConfig() { this.agentMode.getIastScan().setEnabled(true); this.agentMode.getRaspScan().setEnabled(false); + } private void readIastRestrictedConfig() throws RestrictionModeException { @@ -160,18 +207,6 @@ private void readIastRestrictedConfig() throws RestrictionModeException { throw new RestrictionModeException(ACCOUNT_ID_IS_REQUIRED_FOR_IAST_RESTRICTED_MODE); } - restrictionCriteria.getScanTime().setDuration(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SCAN_TIME_DURATION, 5)); - restrictionCriteria.getScanTime().setSchedule(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SCAN_TIME_SCHEDULE, "0 0 0 * * ?")); - if(CronExpression.isValidExpression(restrictionCriteria.getScanTime().getSchedule())){ - try { - restrictionCriteria.getScanTime().setNextScanTime(new CronExpression(restrictionCriteria.getScanTime().getSchedule()).getTimeAfter(new Date())); - } catch (ParseException e) { - throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE, e); - } - } else { - throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE); - } - //Mapping parameters List> mappingParameters = NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS, Collections.emptyList()); if(mappingParameters.isEmpty()) { @@ -182,10 +217,6 @@ private void readIastRestrictedConfig() throws RestrictionModeException { // MappingParameters matchingCriteria = mapper.convertValue(mappingParameter, MappingParameters.class); restrictionCriteria.getMappingParameters().add(matchingCriteria); } - //Skip Scan Parameters - restrictionCriteria.getSkipScanParameters().setBody(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_BODY, Collections.emptyList())); - restrictionCriteria.getSkipScanParameters().setHeader(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_HEADER, Collections.emptyList())); - restrictionCriteria.getSkipScanParameters().setQuery(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_QUERY, Collections.emptyList())); //Strict Criteria List> strictCriteria = NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_STRICT, Collections.emptyList()); 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 5766ea20b..cdef3f194 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 @@ -721,9 +721,7 @@ private JavaAgentEventBean setGenericProperties(AbstractOperation objectBean, Ja private JavaAgentEventBean prepareEvent(HttpRequest httpRequestBean, AgentMetaData metaData, VulnerabilityCaseType vulnerabilityCaseType, K2RequestIdentifier k2RequestIdentifier) { - if(AgentConfig.getInstance().getAgentMode().getIastScan().getRestricted()) { - metaData.setSkipScanParameters(AgentConfig.getInstance().getAgentMode().getIastScan().getRestrictionCriteria().getSkipScanParameters()); - } + metaData.setSkipScanParameters(AgentConfig.getInstance().getAgentMode().getSkipScan().getParameters()); JavaAgentEventBean eventBean = new JavaAgentEventBean(); eventBean.setHttpRequest(httpRequestBean); eventBean.setMetaData(metaData); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java index 3113cf3d5..e280ccc2e 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java @@ -69,6 +69,8 @@ public class ControlCommandProcessor implements Runnable { private long receiveTimestamp; + private static Instant iastReplayRequestMsgReceiveTime; + private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); public ControlCommandProcessor(String controlCommandMessage, long receiveTimestamp) { @@ -166,6 +168,7 @@ public void run() { case IntCodeControlCommand.FUZZ_REQUEST: logger.log(LogLevel.FINER, FUZZ_REQUEST + controlCommandMessage, ControlCommandProcessor.class.getName()); + iastReplayRequestMsgReceiveTime = Instant.now(); IASTDataTransferRequestProcessor.getInstance().setLastFuzzCCTimestamp(Instant.now().toEpochMilli()); RestRequestProcessor.processControlCommand(controlCommand); break; @@ -271,4 +274,8 @@ public static void processControlCommand(String controlCommandMessage, long rece ControlCommandProcessorThreadPool.getInstance().executor .submit(new ControlCommandProcessor(controlCommandMessage, receiveTimestamp)); } + + public static Instant getIastReplayRequestMsgReceiveTime() { + return iastReplayRequestMsgReceiveTime; + } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/collectorconfig/AgentMode.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/collectorconfig/AgentMode.java index 6f24cc64f..81183118e 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/collectorconfig/AgentMode.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/collectorconfig/AgentMode.java @@ -5,6 +5,8 @@ import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; import com.newrelic.api.agent.security.schema.policy.IASTScan; import com.newrelic.api.agent.security.schema.policy.RASPScan; +import com.newrelic.api.agent.security.schema.policy.ScanSchedule; +import com.newrelic.api.agent.security.schema.policy.SkipScan; @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder(alphabetic = true) @@ -16,12 +18,18 @@ public class AgentMode { private RASPScan raspScan; + private SkipScan skipScan; + + private ScanSchedule scanSchedule; + public AgentMode() {} public AgentMode(String mode) { this.mode = mode; iastScan = new IASTScan(); raspScan = new RASPScan(); + skipScan = new SkipScan(); + scanSchedule = new ScanSchedule(); } public String getMode() { @@ -48,6 +56,22 @@ public void setRaspScan(RASPScan raspScan) { this.raspScan = raspScan; } + public SkipScan getSkipScan() { + return skipScan; + } + + public void setSkipScan(SkipScan skipScan) { + this.skipScan = skipScan; + } + + public ScanSchedule getScanSchedule() { + return scanSchedule; + } + + public void setScanSchedule(ScanSchedule scanSchedule) { + this.scanSchedule = scanSchedule; + } + @Override public String toString() { return JsonConverter.toJSON(this); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java index 07b3a9609..240dc3591 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java @@ -10,6 +10,7 @@ import com.newrelic.api.agent.security.schema.HttpRequest; import com.newrelic.api.agent.security.schema.policy.MappingParameters; import com.newrelic.api.agent.security.schema.policy.RestrictionCriteria; +import com.newrelic.api.agent.security.schema.policy.SkipScan; import com.newrelic.api.agent.security.utils.logging.LogLevel; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; @@ -23,6 +24,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import java.io.StringReader; import java.util.*; +import java.util.regex.Pattern; public class RestrictionUtility { @@ -40,6 +42,27 @@ public class RestrictionUtility { private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); + public static boolean skippedApiDetected(SkipScan skipScan, HttpRequest httpRequest) { + if (skipScan == null) { + return false; + } + if (httpRequest == null) { + return false; + } + + if(skipScan.getApiRoutes().isEmpty()) { + return false; + } + + for (Pattern pattern : skipScan.getApiRoutes()) { + if (pattern.matcher(httpRequest.getUrl()).matches()) { + return true; + } + } + + return false; + } + public static boolean hasValidAccountId(RestrictionCriteria restrictionCriteria, HttpRequest request) { List accountIds = restrictionCriteria.getAccountInfo().getAccountIds(); if (request == null) { 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 09986e15b..c5cda2b05 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 @@ -147,6 +147,7 @@ private WSClient() throws URISyntaxException { this.addHeader("NR-CSEC-JSON-VERSION", AgentInfo.getInstance().getBuildInfo().getJsonVersion()); this.addHeader("NR-ACCOUNT-ID", AgentConfig.getInstance().getConfig().getCustomerInfo().getAccountId()); this.addHeader("NR-CSEC-IAST-DATA-TRANSFER-MODE", "PULL"); + this.addHeader("NR-CSEC-IGNORED-VUL-CATEGORIES", AgentConfig.getInstance().getAgentMode().getSkipScan().getIastDetectionCategory().getDisabledCategoriesCSV()); Proxy proxy = proxyManager(); if(proxy != null) { this.setProxy(proxy); 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 e32607c94..8f882cdd7 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 @@ -8,7 +8,28 @@ public interface IUtilConstants { String IAST = "IAST"; String IAST_RESTRICTED = "IAST_RESTRICTED"; - String RESTRICTION_CRITERIA_SCAN_TIME = "security.restriction_criteria.scan_time"; + String SCAN_TIME_DELAY = "security.scan_schedule.delay"; + String SCAN_TIME_SCHEDULE = "security.scan_schedule.schedule"; + String SCAN_TIME_DURATION = "security.scan_schedule.duration"; + + String SKIP_IAST_SCAN = "security.skip_iast_scan"; + String SKIP_IAST_SCAN_API = SKIP_IAST_SCAN + ".api"; + String SKIP_IAST_SCAN_PARAMETERS = SKIP_IAST_SCAN + ".parameters"; + String SKIP_IAST_SCAN_PARAMETERS_HEADER = SKIP_IAST_SCAN + ".parameters.header"; + String SKIP_IAST_SCAN_PARAMETERS_QUERY = SKIP_IAST_SCAN + ".parameters.query"; + String SKIP_IAST_SCAN_PARAMETERS_BODY = SKIP_IAST_SCAN + ".parameters.body"; + String SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY = SKIP_IAST_SCAN + ".iast_detection_category"; + String SKIP_INSECURE_SETTINGS = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".insecure_settings"; + String SKIP_INVALID_FILE_ACCESS = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".invalid_file_access"; + String SKIP_SQL_INJECTION = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".sql_injection"; + String SKIP_NOSQL_INJECTION = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".nosql_injection"; + String SKIP_LDAP_INJECTION = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".ldap_injection"; + String SKIP_JAVASCRIPT_INJECTION = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".javascript_injection"; + String SKIP_COMMAND_INJECTION = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".command_injection"; + String SKIP_XPATH_INJECTION = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".xpath_injection"; + String SKIP_SSRF = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".ssrf"; + String SKIP_RXSS = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".rxss"; + String RESTRICTION_CRITERIA_SCAN_TIME_SCHEDULE = "security.restriction_criteria.scan_time.schedule"; String RESTRICTION_CRITERIA_SCAN_TIME_DURATION = "security.restriction_criteria.scan_time.duration"; String RESTRICTION_CRITERIA = "security.restriction_criteria"; 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 3f729a4f7..3c93eb2df 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 @@ -4,17 +4,21 @@ import com.newrelic.agent.security.AgentConfig; 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.os.OsVariablesInstance; import com.newrelic.agent.security.instrumentator.utils.*; import com.newrelic.agent.security.intcodeagent.constants.AgentServices; import com.newrelic.agent.security.intcodeagent.constants.HttpStatusCodes; +import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessor; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.filelogging.LogFileHelper; +import com.newrelic.agent.security.intcodeagent.models.collectorconfig.AgentMode; import com.newrelic.agent.security.intcodeagent.models.javaagent.*; import com.newrelic.agent.security.intcodeagent.utils.EncryptorUtils; import com.newrelic.agent.security.intcodeagent.utils.RestrictionUtility; import com.newrelic.agent.security.intcodeagent.utils.RuntimeErrorReporter; import com.newrelic.api.agent.security.instrumentation.helpers.*; +import com.newrelic.api.agent.security.schema.policy.IastDetectionCategory; 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; @@ -59,6 +63,7 @@ public class Agent implements SecurityAgent { public static final String DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL = "Dropping event as it was generated by agent internal API call : "; private static final AtomicBoolean firstEventProcessed = new AtomicBoolean(false); public static final String ERROR_WHILE_GENERATING_TRACE_ID_FOR_CATEGORY_S = "Error while generating trace id for category : %s"; + public static final String SKIPPING_THE_API_S_AS_IT_IS_PART_OF_THE_SKIP_SCAN_LIST = "Skipping the API %s as it is part of the skip scan list"; private AgentInfo info; @@ -163,18 +168,26 @@ private void triggerNrSecurity() { } private void scheduleShutdownTrigger() { - if(AgentConfig.getInstance().getAgentMode().getIastScan().getEnabled() && AgentConfig.getInstance().getAgentMode().getIastScan().getRestricted()){ - int duration = AgentConfig.getInstance().getAgentMode().getIastScan().getRestrictionCriteria().getScanTime().getDuration(); + if(AgentConfig.getInstance().getAgentMode().getScanSchedule().getDuration() > 0) { + int duration = AgentConfig.getInstance().getAgentMode().getScanSchedule().getDuration(); Instant now = Instant.now(); - Instant shutdownInstant = now.plus(duration, ChronoUnit.HOURS); + Instant shutdownInstant = now.plus(duration, ChronoUnit.MINUTES); long shutdownTime = shutdownInstant.getEpochSecond() - now.getEpochSecond(); - SchedulerHelper.getInstance().scheduleIastTrigger(this::IastRestrictedShutdown, shutdownTime, TimeUnit.SECONDS); + SchedulerHelper.getInstance().scheduleIastTrigger(this::IastShutdown, shutdownTime, TimeUnit.SECONDS); } } + private void IastShutdown() { + if(ControlCommandProcessor.getIastReplayRequestMsgReceiveTime().isBefore(Instant.now().minus(5, ChronoUnit.MINUTES))){ + logger.log(LogLevel.WARNING, "IAST scan is still in progress, may have undetected vulnerabilities. Please increase scan duration and restart application.", Agent.class.getName()); + } + logger.log(LogLevel.FINER, "Scan duration completed, IAST Scan shutting down.", Agent.class.getName()); + InstrumentationUtils.shutdownLogic(); + } + private void IastRestrictedShutdown() { InstrumentationUtils.shutdownLogic(); - long delay = config.trigerIAST(); + long delay = config.triggerIAST(); SchedulerHelper.getInstance().scheduleIastTrigger(this::triggerNrSecurity, delay, TimeUnit.MILLISECONDS); } @@ -229,6 +242,11 @@ private void startK2Services() { } + @Override + public IastDetectionCategory getIastDetectionCategory() { + return AgentConfig.getInstance().getAgentMode().getSkipScan().getIastDetectionCategory(); + } + @Override public boolean refreshState(java.net.URL agentJarURL, Instrumentation instrumentation) { /** @@ -290,7 +308,13 @@ public void registerOperation(AbstractOperation operation) { boolean lockAcquired = ThreadLocalLockHelper.acquireLock(); try { if(lockAcquired) { + SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); + if(RestrictionUtility.skippedApiDetected(AgentConfig.getInstance().getAgentMode().getSkipScan(), securityMetaData.getRequest())){ + logger.log(LogLevel.FINER, String.format(SKIPPING_THE_API_S_AS_IT_IS_PART_OF_THE_SKIP_SCAN_LIST, securityMetaData.getRequest().getUrl()), Agent.class.getName()); + return; + } + if (securityMetaData != null && securityMetaData.getRequest().getIsGrpc()) { securityMetaData.getRequest().setBody( new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_REQUEST_DATA, List.class)))); 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 3f47b0954..931b5e0a4 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 @@ -8,6 +8,7 @@ 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.schema.policy.IastDetectionCategory; import com.newrelic.api.agent.security.utils.logging.LogLevel; import java.lang.instrument.Instrumentation; @@ -24,6 +25,7 @@ public class Agent implements SecurityAgent { public static final String OPERATIONS = "operations"; public static final String EXIT_OPERATIONS = "exit-operations"; private static Agent instance; + private final IastDetectionCategory defaultIastDetectionCategory = new IastDetectionCategory(); private AgentPolicy policy = new AgentPolicy(); @@ -50,6 +52,11 @@ private Agent() { private void initialise() { } + @Override + public IastDetectionCategory getIastDetectionCategory() { + return defaultIastDetectionCategory; + } + @Override public boolean refreshState(URL agentJarURL, Instrumentation instrumentation) { return true; 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 d5e0f6e74..1a05caf52 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 @@ -12,6 +12,7 @@ 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.schema.policy.IastDetectionCategory; import com.newrelic.api.agent.security.utils.logging.LogLevel; import java.lang.instrument.Instrumentation; @@ -25,11 +26,17 @@ class NoOpAgent implements SecurityAgent { private static final SecurityAgent INSTANCE = new NoOpAgent(); public static final String EMPTY = ""; + private final IastDetectionCategory defaultIastDetectionCategory = new IastDetectionCategory(); public static SecurityAgent getInstance() { return INSTANCE; } + @Override + public IastDetectionCategory getIastDetectionCategory() { + return defaultIastDetectionCategory; + } + @Override public boolean refreshState(URL agentJarURL, Instrumentation instrumentation) { return true; 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 82b573974..bf977d776 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 @@ -11,6 +11,7 @@ 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.schema.policy.IastDetectionCategory; import com.newrelic.api.agent.security.utils.logging.LogLevel; import java.lang.instrument.Instrumentation; @@ -22,6 +23,8 @@ */ public interface SecurityAgent { + IastDetectionCategory getIastDetectionCategory(); + boolean refreshState(URL agentJarURL, Instrumentation instrumentation); boolean deactivateSecurity(); 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 e5fc7954f..ffc269e9a 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 @@ -186,7 +186,7 @@ public static void releaseFileLock() { } catch (Throwable ignored){} } - private static String getNrSecCustomAttribName() { + public static String getNrSecCustomAttribName() { return NR_SEC_CUSTOM_ATTRIB_NAME + Thread.currentThread().getId(); } } 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 8d4cf3f0f..36e7b1ba5 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 @@ -1,6 +1,7 @@ package com.newrelic.api.agent.security.instrumentation.helpers; import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import java.util.regex.Pattern; @@ -49,6 +50,64 @@ public static boolean isLockAcquired(String nrSecCustomAttrName, int hashCode) { return false; } + public static boolean acquireLockIfPossible(VulnerabilityCaseType caseType, String nrSecCustomAttrName, int hashCode) { + boolean enabled = false; + if(!NewRelicSecurity.isHookProcessingActive()) { + return false; + } + switch (caseType) { + case SYSTEM_COMMAND: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getCommandInjectionEnabled(); + break; + case FILE_OPERATION: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getInvalidFileAccessEnabled(); + break; + case SQL_DB_COMMAND: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getSqlInjectionEnabled(); + break; + case NOSQL_DB_COMMAND: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getNoSqlInjectionEnabled(); + break; + case DYNAMO_DB_COMMAND: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getNoSqlInjectionEnabled(); + break; + case HTTP_REQUEST: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getSsrfEnabled(); + break; + case LDAP: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getLdapInjectionEnabled(); + break; + case XPATH: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getXpathInjectionEnabled(); + break; + case REFLECTED_XSS: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled(); + break; + case FILE_INTEGRITY: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getInvalidFileAccessEnabled(); + break; + case JAVASCRIPT_INJECTION: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getJavascriptInjectionEnabled(); + break; + case XQUERY_INJECTION: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getXpathInjectionEnabled(); + break; + case SECURE_COOKIE: + case CRYPTO: + case RANDOM: + case TRUSTBOUNDARY: + case HASH: + enabled = NewRelicSecurity.getAgent().getIastDetectionCategory().getInsecureSettingsEnabled(); + break; + default: + break; + } + if(enabled) { + return false; + } + return acquireLockIfPossible(nrSecCustomAttrName, hashCode); + } + public static boolean acquireLockIfPossible(String nrSecCustomAttrName, int hashCode) { try { if (NewRelicSecurity.isHookProcessingActive() && @@ -68,6 +127,10 @@ public static void releaseLock(String nrSecCustomAttrName, int hashCode) { } catch (Throwable ignored){} } + public static boolean acquireLockIfPossible(VulnerabilityCaseType caseType, String nrSecCustomAttrName) { + return acquireLockIfPossible(caseType, nrSecCustomAttrName, 0); + } + public static boolean acquireLockIfPossible(String nrSecCustomAttrName) { return acquireLockIfPossible(nrSecCustomAttrName, 0); } @@ -75,4 +138,8 @@ public static boolean acquireLockIfPossible(String nrSecCustomAttrName) { public static void releaseLock(String nrSecCustomAttrName) { releaseLock(nrSecCustomAttrName, 0); } + + public static void onTransactionFinish() { + + } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/JdbcHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/JdbcHelper.java index b4081527b..265ce1e79 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/JdbcHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/JdbcHelper.java @@ -85,14 +85,10 @@ public static boolean acquireLockIfPossible() { } public static void releaseLock() { - try { - if(NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), null); - } - } catch (Throwable ignored){} + GenericHelper.releaseLock(JdbcHelper.getNrSecCustomAttribName()); } - private static String getNrSecCustomAttribName() { + public static String getNrSecCustomAttribName() { return NR_SEC_CUSTOM_ATTRIB_NAME + Thread.currentThread().getId(); } 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 c23e60285..680dec0ec 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 @@ -3,6 +3,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.R2DBCVendor; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SQLOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -72,23 +73,12 @@ public static boolean isLockAcquired() { return false; } - public static boolean acquireLockIfPossible() { - try { - if (NewRelicSecurity.isHookProcessingActive() && - !isLockAcquired()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), true); - return true; - } - } catch (Throwable ignored){} - return false; + public static boolean acquireLockIfPossible(VulnerabilityCaseType sqlDbCommand) { + return GenericHelper.acquireLockIfPossible(sqlDbCommand, getNrSecCustomAttribName()); } public static void releaseLock() { - try { - if(NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), null); - } - } catch (Throwable ignored){} + GenericHelper.releaseLock(getNrSecCustomAttribName()); } private static String getNrSecCustomAttribName() { diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java new file mode 100644 index 000000000..46933e1b0 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java @@ -0,0 +1,167 @@ +package com.newrelic.api.agent.security.schema.policy; + +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; + +public class IastDetectionCategory { + + public static final String STR_COMMA = ","; + Boolean sqlInjectionEnabled = true; + Boolean insecureSettingsEnabled = true; + Boolean invalidFileAccessEnabled = true; + Boolean noSqlInjectionEnabled = true; + Boolean rxssEnabled = true; + Boolean commandInjectionEnabled = true; + Boolean ldapInjectionEnabled = true; + Boolean javascriptInjectionEnabled = true; + Boolean xpathInjectionEnabled = true; + Boolean ssrfEnabled = true; + + private String disabledCategoriesCSV; + + public IastDetectionCategory() { + } + + public Boolean getSqlInjectionEnabled() { + return sqlInjectionEnabled; + } + + public void setSqlInjectionEnabled(Boolean sqlInjectionEnabled) { + this.sqlInjectionEnabled = sqlInjectionEnabled; + } + + public Boolean getInsecureSettingsEnabled() { + return insecureSettingsEnabled; + } + + public void setInsecureSettingsEnabled(Boolean insecureSettingsEnabled) { + this.insecureSettingsEnabled = insecureSettingsEnabled; + } + + public Boolean getInvalidFileAccessEnabled() { + return invalidFileAccessEnabled; + } + + public void setInvalidFileAccessEnabled(Boolean invalidFileAccessEnabled) { + this.invalidFileAccessEnabled = invalidFileAccessEnabled; + } + + public Boolean getNoSqlInjectionEnabled() { + return noSqlInjectionEnabled; + } + + public void setNoSqlInjectionEnabled(Boolean noSqlInjectionEnabled) { + this.noSqlInjectionEnabled = noSqlInjectionEnabled; + } + + public Boolean getRxssEnabled() { + return rxssEnabled; + } + + public void setRxssEnabled(Boolean rxssEnabled) { + this.rxssEnabled = rxssEnabled; + } + + public Boolean getCommandInjectionEnabled() { + return commandInjectionEnabled; + } + + public void setCommandInjectionEnabled(Boolean commandInjectionEnabled) { + this.commandInjectionEnabled = commandInjectionEnabled; + } + + public Boolean getLdapInjectionEnabled() { + return ldapInjectionEnabled; + } + + public void setLdapInjectionEnabled(Boolean ldapInjectionEnabled) { + this.ldapInjectionEnabled = ldapInjectionEnabled; + } + + public Boolean getJavascriptInjectionEnabled() { + return javascriptInjectionEnabled; + } + + public void setJavascriptInjectionEnabled(Boolean javascriptInjectionEnabled) { + this.javascriptInjectionEnabled = javascriptInjectionEnabled; + } + + public Boolean getXpathInjectionEnabled() { + return xpathInjectionEnabled; + } + + public void setXpathInjectionEnabled(Boolean xpathInjectionEnabled) { + this.xpathInjectionEnabled = xpathInjectionEnabled; + } + + public Boolean getSsrfEnabled() { + return ssrfEnabled; + } + + public void setSsrfEnabled(Boolean ssrfEnabled) { + this.ssrfEnabled = ssrfEnabled; + } + + public void generateDisabledCategoriesCSV() { + StringBuilder disabledCategoriesCSVBuilder = new StringBuilder(); + if (sqlInjectionEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.SQL_DB_COMMAND); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (insecureSettingsEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.HASH); + disabledCategoriesCSVBuilder.append(STR_COMMA); + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.RANDOM); + disabledCategoriesCSVBuilder.append(STR_COMMA); + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.SECURE_COOKIE); + disabledCategoriesCSVBuilder.append(STR_COMMA); + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.TRUSTBOUNDARY); + disabledCategoriesCSVBuilder.append(STR_COMMA); + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.CRYPTO); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (invalidFileAccessEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.FILE_INTEGRITY); + disabledCategoriesCSVBuilder.append(STR_COMMA); + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.FILE_OPERATION); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (noSqlInjectionEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.NOSQL_DB_COMMAND); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (rxssEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.REFLECTED_XSS); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (commandInjectionEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.SYSTEM_COMMAND); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (ldapInjectionEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.LDAP); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (javascriptInjectionEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.JAVASCRIPT_INJECTION); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (xpathInjectionEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.XPATH); + disabledCategoriesCSVBuilder.append(STR_COMMA); + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.XQUERY_INJECTION); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (ssrfEnabled) { + disabledCategoriesCSVBuilder.append(VulnerabilityCaseType.HTTP_REQUEST); + disabledCategoriesCSVBuilder.append(STR_COMMA); + } + if (disabledCategoriesCSVBuilder.length() > 0) { + disabledCategoriesCSVBuilder.deleteCharAt(disabledCategoriesCSVBuilder.length() - 1); + } + disabledCategoriesCSV = disabledCategoriesCSVBuilder.toString(); + } + + public String getDisabledCategoriesCSV() { + return disabledCategoriesCSV; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java index 7a9e227cb..8d87ce1c6 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java @@ -5,7 +5,7 @@ public class RestrictionCriteria { - private ScanTime scanTime = new ScanTime(); + private ScanSchedule scanSchedule = new ScanSchedule(); private AccountInfo accountInfo = new AccountInfo(); @@ -18,12 +18,12 @@ public class RestrictionCriteria { public RestrictionCriteria() { } - public ScanTime getScanTime() { - return scanTime; + public ScanSchedule getScanTime() { + return scanSchedule; } - public void setScanTime(ScanTime scanTime) { - this.scanTime = scanTime; + public void setScanTime(ScanSchedule scanSchedule) { + this.scanSchedule = scanSchedule; } public AccountInfo getAccountInfo() { diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanTime.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanSchedule.java similarity index 71% rename from newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanTime.java rename to newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanSchedule.java index dd5d8901f..75084afb0 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanTime.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanSchedule.java @@ -2,15 +2,17 @@ import java.util.Date; -public class ScanTime { +public class ScanSchedule { - private int duration; + private int duration = -1; private String schedule; private Date nextScanTime; - public ScanTime() { + private int delay = 0; + + public ScanSchedule() { } public int getDuration() { @@ -36,4 +38,12 @@ public Date getNextScanTime() { public void setNextScanTime(Date nextScanTime) { this.nextScanTime = nextScanTime; } + + public int getDelay() { + return delay; + } + + public void setDelay(int delay) { + this.delay = delay; + } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScan.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScan.java new file mode 100644 index 000000000..042f28366 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScan.java @@ -0,0 +1,55 @@ +package com.newrelic.api.agent.security.schema.policy; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +public class SkipScan { + private List apis = new ArrayList<>(); + + private List apiRoutes = new ArrayList<>(); + + private SkipScanParameters parameters = new SkipScanParameters(); + + private IastDetectionCategory iastDetectionCategory = new IastDetectionCategory(); + + public SkipScan() { + } + + public List getApis() { + return apis; + } + + public void setApis(List apis) { + this.apis = apis; + if(apis != null) { + for (String api : apis) { + apiRoutes.add(Pattern.compile(api)); + } + } + } + + public List getApiRoutes() { + return apiRoutes; + } + + public void setApiRoutes(List apiRoutes) { + this.apiRoutes = apiRoutes; + } + + public SkipScanParameters getParameters() { + return parameters; + } + + public void setParameters(SkipScanParameters parameters) { + this.parameters = parameters; + } + + public IastDetectionCategory getIastDetectionCategory() { + return iastDetectionCategory; + } + + public void setIastDetectionCategory(IastDetectionCategory iastDetectionCategory) { + this.iastDetectionCategory = iastDetectionCategory; + } +} From 8e12347e7816a6644bc5936a880803b67496f5af Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 14 Aug 2024 10:55:51 +0530 Subject: [PATCH 085/122] Add feature to IAST_SCAN_IGNORE --- .../http/scaladsl/server/AkkaCoreUtils.java | 3 ++ .../akka/http/scaladsl/AkkaCoreUtils.java | 3 ++ .../scaladsl/HttpExt_Instrumentation.java | 7 +-- .../akka/http/scaladsl/AkkaCoreUtils.java | 3 ++ .../scaladsl/HttpExt_Instrumentation.java | 7 +-- .../akka/http/scaladsl/AkkaCoreUtils.java | 3 ++ .../scaladsl/HttpExt_Instrumentation.java | 7 +-- .../akka/http/scaladsl/AkkaCoreUtils.java | 3 ++ .../scaladsl/HttpExt_Instrumentation.java | 7 +-- .../LdapAsyncConnection_Instrumentation.java | 11 ++-- .../api/LdapConnection_Instrumentation.java | 11 ++-- .../org/asynchttpclient/AsynchttpHelper.java | 12 ++--- .../AsyncHttpClient_Instrumentation.java | 3 +- .../BuilderSupport_Instrumentation.java | 7 +-- .../core/SessionManager_Instrumentation.java | 3 +- .../core/SimpleStatement_Instrumentation.java | 4 +- .../cassandra3/CassandraUtils.java | 4 +- .../driver/core/Session_Instrumentation.java | 3 +- .../cassandra4/CassandraUtils.java | 4 +- ...hContextReferenceImpl_Instrumentation.java | 13 ++--- .../AmazonDynamoDBClient_Instrumentation.java | 3 +- .../dynamodb_1_11_390/DynamoDBUtil.java | 5 +- .../AmazonDynamoDBClient_Instrumentation.java | 3 +- .../dynamodb_1_11_453/DynamoDBUtil.java | 5 +- .../AmazonDynamoDBClient_Instrumentation.java | 3 +- .../dynamodb_1_11_459/DynamoDBUtil.java | 5 +- .../AmazonDynamoDBClient_Instrumentation.java | 3 +- .../dynamodb_1_11_80/DynamoDBUtil.java | 5 +- .../dynamodb_210/DynamoDBUtil.java | 3 +- .../AsyncClientHandler_Instrumentation.java | 5 +- .../SyncClientHandler_Instrumentation.java | 5 +- .../dynamodb_212/DynamoDBUtil.java | 5 +- .../AsyncClientHandler_Instrumentation.java | 6 +-- .../SyncClientHandler_Instrumentation.java | 6 +-- .../dynamodb_215/DynamoDBUtil.java | 5 +- .../AsyncClientHandler_Instrumentation.java | 6 +-- .../SyncClientHandler_Instrumentation.java | 6 +-- .../random/java/io/File_Instrumentation.java | 16 ++---- .../io/FileInputStream_Instrumentation.java | 16 +++--- .../io/FileOutputStream_Instrumentation.java | 16 +++--- .../java/java/io/File_Instrumentation.java | 50 ++++++++----------- .../io/RandomAccessFile_Instrumentation.java | 16 +++--- .../java/nio/file/Files_Instrumentation.java | 16 ++---- .../FileSystemProvider_Instrumentation.java | 43 ++++++++-------- .../PolyglotContextImpl_Instrumentation.java | 7 +-- .../PolyglotContextImpl_Instrumentation.java | 7 +-- .../grpc1220/GrpcClientUtils.java | 26 ++-------- .../grpc1220/GrpcServerUtils.java | 3 ++ .../io/grpc/ClientCall_Instrumentation.java | 3 +- .../grpc140/GrpcClientUtils.java | 27 ++-------- .../grpc140/GrpcServerUtils.java | 3 ++ .../io/grpc/ClientCall_Instrumentation.java | 3 +- .../grpc1400/GrpcClientUtils.java | 25 ++-------- .../grpc1400/GrpcServerUtils.java | 3 ++ .../io/grpc/ClientCall_Instrumentation.java | 3 +- .../HttpAsyncClient4_Instrumentation.java | 17 ++++--- .../HttpMethodBase_Instrumentation.java | 7 +-- .../HttpClient_Instrumentation.java | 21 ++++---- .../HttpAsyncClient_Instrumentation.java | 7 +-- .../HttpClient_Instrumentation.java | 21 ++++---- .../http/HttpClientImpl_Instrumentation.java | 7 +-- .../javax/naming/Context_Instrumentation.java | 13 ++--- .../directory/DirContext_Instrumentation.java | 13 ++--- .../xpath/internal/XPath_Instrumentation.java | 9 ++-- .../xml/xpath/XPath_Instrumentation.java | 13 ++--- .../org/jaxen/BaseXPath_Instrumentation.java | 7 +-- .../org/jaxen/BaseXPath_Instrumentation.java | 7 +-- .../jcache_1_0_0/JCacheHelper.java | 5 +- .../javax/cache/Cache_Instrumentation.java | 31 ++++++------ .../PreparedStatement_Instrumentation.java | 20 +++----- .../java/sql/Statement_Instrumentation.java | 36 ++++++------- ...JtdsPreparedStatement_Instrumentation.java | 14 +++--- .../jdbc/JtdsStatement_Instrumentation.java | 26 +++++----- ...bstractJdbc2Statement_Instrumentation.java | 24 ++++----- .../jdbc/PgStatement_Instrumentation.java | 20 ++++---- .../jedis_2_7_1/JedisHelper.java | 5 +- .../jedis/Connection_Instrumentation.java | 3 +- .../jedis_3_0_0/JedisHelper.java | 5 +- .../jedis/Connection_Instrumentation.java | 3 +- .../jedis_4_0_0/JedisHelper.java | 5 +- .../jedis/Connection_Instrumentation.java | 3 +- .../ContainerResponse_Instrumentation.java | 3 +- .../ContainerResponse_Instrumentation.java | 3 +- .../ContainerResponse_Instrumentation.java | 3 +- .../jetty11/HttpServletHelper.java | 6 ++- .../jetty12/server/HttpServletHelper.java | 6 ++- .../jetty9/HttpServletHelper.java | 6 ++- .../AbstractOperation_Instrumentation.java | 10 ++-- .../AbstractOperation_Instrumentation.java | 7 +-- ...actRedisAsyncCommands_Instrumentation.java | 7 +-- ...actRedisAsyncCommands_Instrumentation.java | 7 +-- .../java/util/Random_Instrumentation.java | 21 ++++---- .../CommandReadOperation_Instrumentation.java | 5 +- ...CommandWriteOperation_Instrumentation.java | 5 +- .../OperationExecutor_Instrumentation.java | 9 ++-- .../instrumentation/mongo/MongoUtil.java | 5 +- .../OperationExecutor_Instrumentation.java | 13 ++--- .../CommandReadOperation_Instrumentation.java | 5 +- ...CommandWriteOperation_Instrumentation.java | 5 +- .../instrumentation/mongo/MongoUtil.java | 5 +- .../OperationExecutor_Instrumentation.java | 13 ++--- .../CommandReadOperation_Instrumentation.java | 5 +- ...CommandWriteOperation_Instrumentation.java | 5 +- .../instrumentation/mongo/MongoUtil.java | 5 +- .../OperationExecutor_Instrumentation.java | 13 ++--- .../CommandReadOperation_Instrumentation.java | 5 +- ...CommandWriteOperation_Instrumentation.java | 5 +- .../instrumentation/mongo/MongoUtil.java | 5 +- ...ttpRequestToMuleEvent_Instrumentation.java | 7 ++- .../async/RequestHandler_Instrumentation.java | 6 ++- ...ttpRequestToMuleEvent_Instrumentation.java | 6 ++- .../async/RequestHandler_Instrumentation.java | 6 ++- .../NashornScriptEngine_Instrumentation.java | 9 ++-- ...ChannelInboundHandler_Instrumentation.java | 3 +- ...hannelOutboundHandler_Instrumentation.java | 3 +- .../io/netty400/utils/NettyUtils.java | 18 ++----- ...ChannelInboundHandler_Instrumentation.java | 3 +- ...hannelOutboundHandler_Instrumentation.java | 3 +- .../io/netty400/utils/NettyUtils.java | 18 ++----- .../ning/http_1_0/NingHelper.java | 8 ++- .../AsyncHttpProvider_Instrumentation.java | 3 +- .../ning/http_1_1/NingHelper.java | 5 +- .../AsyncHttpProvider_Instrumentation.java | 3 +- .../ning/http_1_6_1/NingHelper.java | 5 +- .../AsyncHttpProvider_Instrumentation.java | 3 +- .../okhttp30/OkhttpHelper.java | 30 +---------- .../okhttp30/RealCall_Instrumentation.java | 14 ++---- .../okhttp35/OkhttpHelper.java | 30 +---------- .../http/HttpCodec_Instrumentation.java | 16 ++---- .../ExchangeCodec_Instrumentation.java | 14 ++---- .../okhttp40/OkhttpHelper.java | 30 +---------- .../io/r2dbc/spi/Batch_Instrumentation.java | 3 +- .../io/r2dbc/spi/Statement_Instrumention.java | 3 +- .../h2/client/Client_Instrumentation.java | 11 +--- .../ScriptRuntime_Instrumentation.java | 7 +-- .../saxpath/XPathReader_Instrumentation.java | 7 +-- .../servlet/FilterChain_Instrumentation.java | 3 ++ .../javax/servlet/Filter_Instrumentation.java | 3 ++ .../servlet/Servlet_Instrumentation.java | 3 ++ .../servlet/FilterChain_Instrumentation.java | 3 ++ .../servlet/Filter_Instrumentation.java | 3 ++ .../servlet/Servlet_Instrumentation.java | 3 ++ .../servlet/FilterChain_Instrumentation.java | 3 ++ .../servlet/Filter_Instrumentation.java | 3 ++ .../servlet/Servlet_Instrumentation.java | 3 ++ .../ResponseRendering_Instrumentation.java | 3 +- .../SprayToResponseMarshallingContext.java | 3 +- .../ExchangeFunction_Instrumentation.java | 7 +-- .../MemcachedClient_Instrumentation.java | 7 +-- .../httpserver/Filter_Instrumentation.java | 3 ++ .../HttpHandler_Instrumentation.java | 3 ++ .../sdk/LDAPInterface_Instrumentation.java | 7 +-- .../vertx/VertxClientHelper.java | 5 +- ...HttpClientRequestImpl_Instrumentation.java | 5 +- .../vertx/VertxClientHelper.java | 5 +- ...HttpClientRequestImpl_Instrumentation.java | 5 +- ...HttpClientRequestImpl_Instrumentation.java | 13 ++--- .../vertx/web/VertxClientHelper.java | 5 +- ...HttpClientRequestImpl_Instrumentation.java | 7 +-- .../apache/xpath/XPath_Instrumentation.java | 7 +-- 160 files changed, 663 insertions(+), 732 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 3a243a2a5..430dedb60 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 @@ -60,6 +60,9 @@ public static boolean acquireServletLockIfPossible() { } public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, String className, String methodName, Token token) { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } try { token.linkAndExpire(); ServletHelper.executeBeforeExitingTransaction(); 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 904e8fb83..cfd6c386c 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 @@ -63,6 +63,9 @@ public static boolean acquireServletLockIfPossible() { public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder response, String contentType, int responseCode, String className, String methodName, Token token) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } token.linkAndExpire(); if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive()){ diff --git a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java index e28c30ad5..deada6535 100644 --- a/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java +++ b/instrumentation-security/akka-http-core-10.0/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java @@ -20,6 +20,7 @@ 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.VulnerabilityCaseType; 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; @@ -65,7 +66,7 @@ public Future bindAndHandleSync( public Future singleRequest(HttpRequest httpRequest, HttpsConnectionContext connectionContext, ConnectionPoolSettings settings, LoggingAdapter log, Materializer fm) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -163,9 +164,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { try { - return GenericHelper.acquireLockIfPossible(AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); + return GenericHelper.acquireLockIfPossible(httpRequest, AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); } catch (Throwable ignored) { } return false; 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 064790902..124589903 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 @@ -63,6 +63,9 @@ public static boolean acquireServletLockIfPossible() { public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, int responseCode, String className, String methodName, Token token) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } token.linkAndExpire(); if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive()){ diff --git a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java index ea8efb5ba..65d5da00b 100644 --- a/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java +++ b/instrumentation-security/akka-http-core-2.11_10.0.11/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java @@ -20,6 +20,7 @@ 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.VulnerabilityCaseType; 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; @@ -66,7 +67,7 @@ public Future bindAndHandleSync( public Future singleRequestImpl(HttpRequest httpRequest, HttpsConnectionContext connectionContext, ConnectionPoolSettings poolSettings, LoggingAdapter loggingAdapter) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); @@ -167,9 +168,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { try { - return GenericHelper.acquireLockIfPossible(AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); + return GenericHelper.acquireLockIfPossible(httpRequest, AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java index 0a0d4fb68..cc2c65f3a 100644 --- a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java +++ b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/AkkaCoreUtils.java @@ -63,6 +63,9 @@ public static boolean acquireServletLockIfPossible() { public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, String className, String methodName, Token token) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } token.linkAndExpire(); if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive()){ return; diff --git a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java index ea8efb5ba..65d5da00b 100644 --- a/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java +++ b/instrumentation-security/akka-http-core-2.13_10.1.8/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java @@ -20,6 +20,7 @@ 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.VulnerabilityCaseType; 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; @@ -66,7 +67,7 @@ public Future bindAndHandleSync( public Future singleRequestImpl(HttpRequest httpRequest, HttpsConnectionContext connectionContext, ConnectionPoolSettings poolSettings, LoggingAdapter loggingAdapter) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); @@ -167,9 +168,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { try { - return GenericHelper.acquireLockIfPossible(AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); + return GenericHelper.acquireLockIfPossible(httpRequest, AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); } catch (Throwable ignored) { } return false; 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 88a5c57bd..0f36ab5e6 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 @@ -63,6 +63,9 @@ public static boolean acquireServletLockIfPossible() { public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, int responseCode, String className, String methodName, Token token) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } token.linkAndExpire(); if(!isServletLockAcquired || !NewRelicSecurity.isHookProcessingActive()){ return; diff --git a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java index 623f578e7..41c69c12e 100644 --- a/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java +++ b/instrumentation-security/akka-http-core-2.13_10.2.0/src/main/scala/akka/http/scaladsl/HttpExt_Instrumentation.java @@ -22,6 +22,7 @@ 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.VulnerabilityCaseType; 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; @@ -74,7 +75,7 @@ public Future singleRequest(HttpRequest httpRequest, HttpsConnecti LoggingAdapter loggingAdapter) { final Segment segment = NewRelic.getAgent().getTransaction().startSegment("Akka", "singleRequest"); - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData(); @@ -176,9 +177,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { try { - return GenericHelper.acquireLockIfPossible(AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); + return GenericHelper.acquireLockIfPossible(httpRequest, AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/apache-ldap/src/main/java/org/apache/directory/ldap/client/api/LdapAsyncConnection_Instrumentation.java b/instrumentation-security/apache-ldap/src/main/java/org/apache/directory/ldap/client/api/LdapAsyncConnection_Instrumentation.java index 3b61abe30..6c7a53102 100644 --- a/instrumentation-security/apache-ldap/src/main/java/org/apache/directory/ldap/client/api/LdapAsyncConnection_Instrumentation.java +++ b/instrumentation-security/apache-ldap/src/main/java/org/apache/directory/ldap/client/api/LdapAsyncConnection_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.LDAPOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -61,16 +62,16 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType caseType) { try { - return GenericHelper.acquireLockIfPossible(LDAPUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(caseType, LDAPUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } public SearchFuture searchAsync(Dn baseDn, String filter, SearchScope scope, String... attributes ) throws LdapException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(baseDn.getName(), filter, LDAPUtils.METHOD_SEARCH_ASYNC); @@ -90,7 +91,7 @@ public SearchFuture searchAsync(Dn baseDn, String filter, SearchScope scope, Str public SearchFuture searchAsync(String baseDn, String filter, SearchScope scope, String... attributes ) throws LdapException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(baseDn, filter, LDAPUtils.METHOD_SEARCH_ASYNC); @@ -109,7 +110,7 @@ public SearchFuture searchAsync(String baseDn, String filter, SearchScope scope, } public SearchFuture searchAsync( SearchRequest searchRequest ) throws LdapException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(searchRequest.getBase().getName(), searchRequest.getFilter().toString(), LDAPUtils.METHOD_SEARCH_ASYNC); diff --git a/instrumentation-security/apache-ldap/src/main/java/org/apache/directory/ldap/client/api/LdapConnection_Instrumentation.java b/instrumentation-security/apache-ldap/src/main/java/org/apache/directory/ldap/client/api/LdapConnection_Instrumentation.java index 12fe4c455..e8283a5fe 100644 --- a/instrumentation-security/apache-ldap/src/main/java/org/apache/directory/ldap/client/api/LdapConnection_Instrumentation.java +++ b/instrumentation-security/apache-ldap/src/main/java/org/apache/directory/ldap/client/api/LdapConnection_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.LDAPOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -61,16 +62,16 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType caseType) { try { - return GenericHelper.acquireLockIfPossible(LDAPUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(caseType, LDAPUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } public EntryCursor search(Dn baseDn, String filter, SearchScope scope, String... attributes ) throws LdapException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(baseDn.getName(), filter, LDAPUtils.METHOD_SEARCH); @@ -90,7 +91,7 @@ public EntryCursor search(Dn baseDn, String filter, SearchScope scope, String... public EntryCursor search( String baseDn, String filter, SearchScope scope, String... attributes ) throws LdapException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(baseDn, filter, LDAPUtils.METHOD_SEARCH); @@ -109,7 +110,7 @@ public EntryCursor search( String baseDn, String filter, SearchScope scope, Stri } public SearchCursor search(SearchRequest searchRequest ) throws LdapException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(searchRequest.getBase().getName(), searchRequest.getFilter().toString(), LDAPUtils.METHOD_SEARCH); 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 94062e622..8088f8749 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 @@ -5,6 +5,7 @@ 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; import com.newrelic.api.agent.security.utils.SSRFUtils; @@ -36,15 +37,8 @@ public static boolean isLockAcquired() { return false; } - public static boolean acquireLockIfPossible() { - try { - if (NewRelicSecurity.isHookProcessingActive() && - !isLockAcquired()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), true); - return true; - } - } catch (Throwable ignored){} - return false; + public static boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, getNrSecCustomAttribName()); } public static void releaseLock() { diff --git a/instrumentation-security/async-http-client-2.0.0/src/main/java/org/asynchttpclient/AsyncHttpClient_Instrumentation.java b/instrumentation-security/async-http-client-2.0.0/src/main/java/org/asynchttpclient/AsyncHttpClient_Instrumentation.java index 9c12e6542..2a538a84b 100644 --- a/instrumentation-security/async-http-client-2.0.0/src/main/java/org/asynchttpclient/AsyncHttpClient_Instrumentation.java +++ b/instrumentation-security/async-http-client-2.0.0/src/main/java/org/asynchttpclient/AsyncHttpClient_Instrumentation.java @@ -9,6 +9,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -27,7 +28,7 @@ public abstract class AsyncHttpClient_Instrumentation { public ListenableFuture executeRequest(Request request, AsyncHandler handler) { URI uri = null; - boolean isLockAcquired = AsynchttpHelper.acquireLockIfPossible(); + boolean isLockAcquired = AsynchttpHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { try { diff --git a/instrumentation-security/camel-xpath/src/main/java/org/apache/camel/builder/BuilderSupport_Instrumentation.java b/instrumentation-security/camel-xpath/src/main/java/org/apache/camel/builder/BuilderSupport_Instrumentation.java index 5be2a50df..4c4b94439 100644 --- a/instrumentation-security/camel-xpath/src/main/java/org/apache/camel/builder/BuilderSupport_Instrumentation.java +++ b/instrumentation-security/camel-xpath/src/main/java/org/apache/camel/builder/BuilderSupport_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.XPathOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -56,15 +57,15 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType xpath) { try { - return GenericHelper.acquireLockIfPossible(XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(xpath, XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } public ValueBuilder xpath(String value, Class resultType, Namespaces namespaces) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(value, XPATHUtils.METHOD_XPATH); diff --git a/instrumentation-security/cassandra-datastax-3/src/main/java/com/datastax/driver/core/SessionManager_Instrumentation.java b/instrumentation-security/cassandra-datastax-3/src/main/java/com/datastax/driver/core/SessionManager_Instrumentation.java index 4a3fc9849..fef64e303 100644 --- a/instrumentation-security/cassandra-datastax-3/src/main/java/com/datastax/driver/core/SessionManager_Instrumentation.java +++ b/instrumentation-security/cassandra-datastax-3/src/main/java/com/datastax/driver/core/SessionManager_Instrumentation.java @@ -4,6 +4,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -16,7 +17,7 @@ abstract class SessionManager_Instrumentation { abstract Configuration configuration(); public ResultSetFuture executeAsync(Statement statement) { - boolean isLockAcquired = CassandraUtils.acquireLockIfPossible(statement.hashCode()); + boolean isLockAcquired = CassandraUtils.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, statement.hashCode()); ResultSetFuture result = null; AbstractOperation cqlOperation = null; diff --git a/instrumentation-security/cassandra-datastax-3/src/main/java/com/datastax/driver/core/SimpleStatement_Instrumentation.java b/instrumentation-security/cassandra-datastax-3/src/main/java/com/datastax/driver/core/SimpleStatement_Instrumentation.java index 09621a27f..2d8e68f24 100644 --- a/instrumentation-security/cassandra-datastax-3/src/main/java/com/datastax/driver/core/SimpleStatement_Instrumentation.java +++ b/instrumentation-security/cassandra-datastax-3/src/main/java/com/datastax/driver/core/SimpleStatement_Instrumentation.java @@ -16,7 +16,7 @@ public abstract class SimpleStatement_Instrumentation { public SimpleStatement_Instrumentation(String query, Object... values) { - boolean isLockAcquired = CassandraUtils.acquireLockIfPossible(hashCode()); + boolean isLockAcquired = CassandraUtils.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, hashCode()); try{ if(isLockAcquired){ @@ -41,7 +41,7 @@ public SimpleStatement_Instrumentation(String query, Object... values) { } public SimpleStatement_Instrumentation(String query, Map values){ - boolean isLockAcquired = CassandraUtils.acquireLockIfPossible(hashCode()); + boolean isLockAcquired = CassandraUtils.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, hashCode()); try{ if(isLockAcquired){ diff --git a/instrumentation-security/cassandra-datastax-3/src/main/java/com/newrelic/agent/security/instrumentation/cassandra3/CassandraUtils.java b/instrumentation-security/cassandra-datastax-3/src/main/java/com/newrelic/agent/security/instrumentation/cassandra3/CassandraUtils.java index 8e886e480..f5f3343c4 100644 --- a/instrumentation-security/cassandra-datastax-3/src/main/java/com/newrelic/agent/security/instrumentation/cassandra3/CassandraUtils.java +++ b/instrumentation-security/cassandra-datastax-3/src/main/java/com/newrelic/agent/security/instrumentation/cassandra3/CassandraUtils.java @@ -29,9 +29,9 @@ public class CassandraUtils { public static final String NR_SEC_CASSANDRA_LOCK = "CASSANDRA_OPERATION_LOCK"; public static final String CASSANDRA_DATASTAX_3 = "CASSANDRA-DATASTAX-3"; - public static boolean acquireLockIfPossible(int hashcode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashcode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CASSANDRA_LOCK + hashcode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, NR_SEC_CASSANDRA_LOCK + hashcode); } catch (Exception ignored){ } return false; diff --git a/instrumentation-security/cassandra-datastax-4/src/main/java/com/datastax/driver/core/Session_Instrumentation.java b/instrumentation-security/cassandra-datastax-4/src/main/java/com/datastax/driver/core/Session_Instrumentation.java index 1fead9d5e..bf7e750b5 100644 --- a/instrumentation-security/cassandra-datastax-4/src/main/java/com/datastax/driver/core/Session_Instrumentation.java +++ b/instrumentation-security/cassandra-datastax-4/src/main/java/com/datastax/driver/core/Session_Instrumentation.java @@ -5,6 +5,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -17,7 +18,7 @@ public class Session_Instrumentation { public ResultT execute(RequestT request, GenericType resultType) { AbstractOperation cqlOperation = null; - boolean isLockAcquired = CassandraUtils.acquireLockIfPossible(request.hashCode()); + boolean isLockAcquired = CassandraUtils.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, request.hashCode()); ResultT result = null; try { diff --git a/instrumentation-security/cassandra-datastax-4/src/main/java/com/newrelic/agent/security/instrumentation/cassandra4/CassandraUtils.java b/instrumentation-security/cassandra-datastax-4/src/main/java/com/newrelic/agent/security/instrumentation/cassandra4/CassandraUtils.java index bab7aba4e..be4ff6d1a 100644 --- a/instrumentation-security/cassandra-datastax-4/src/main/java/com/newrelic/agent/security/instrumentation/cassandra4/CassandraUtils.java +++ b/instrumentation-security/cassandra-datastax-4/src/main/java/com/newrelic/agent/security/instrumentation/cassandra4/CassandraUtils.java @@ -31,9 +31,9 @@ public class CassandraUtils { public static final String NR_SEC_CASSANDRA_LOCK = "CASSANDRA_OPERATION_LOCK"; public static final String CASSANDRA_DATASTAX_4 = "CASSANDRA-DATASTAX-4"; - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CASSANDRA_LOCK, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, NR_SEC_CASSANDRA_LOCK, hashCode); } catch (Exception ignored){ } return false; diff --git a/instrumentation-security/commons-jxpath/src/main/java/org/apache/commons/jxpath/ri/compiler/JXPathContextReferenceImpl_Instrumentation.java b/instrumentation-security/commons-jxpath/src/main/java/org/apache/commons/jxpath/ri/compiler/JXPathContextReferenceImpl_Instrumentation.java index f3902044c..b4abba71d 100644 --- a/instrumentation-security/commons-jxpath/src/main/java/org/apache/commons/jxpath/ri/compiler/JXPathContextReferenceImpl_Instrumentation.java +++ b/instrumentation-security/commons-jxpath/src/main/java/org/apache/commons/jxpath/ri/compiler/JXPathContextReferenceImpl_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.XPathOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -18,7 +19,7 @@ public class JXPathContextReferenceImpl_Instrumentation { public Object getValue(String xpath, Expression expr) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(xpath, XPATHUtils.METHOD_GETVALUE); @@ -37,7 +38,7 @@ public Object getValue(String xpath, Expression expr) { } public Iterator iterate(String xpath, Expression expr) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(xpath, XPATHUtils.METHOD_ITERATE); @@ -56,7 +57,7 @@ public Iterator iterate(String xpath, Expression expr) { } public void removePath(String xpath, Expression expr) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(xpath, XPATHUtils.METHOD_REMOVE_PATH); @@ -73,7 +74,7 @@ public void removePath(String xpath, Expression expr) { } public void removeAll(String xpath, Expression expr) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(xpath, XPATHUtils.METHOD_REMOVE_ALL); @@ -129,9 +130,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType xpath) { try { - return GenericHelper.acquireLockIfPossible(XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(xpath, XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/dynamodb-1.11.390/src/main/java/com/amazonaws/services/dynamodbv2_1_11_390/AmazonDynamoDBClient_Instrumentation.java b/instrumentation-security/dynamodb-1.11.390/src/main/java/com/amazonaws/services/dynamodbv2_1_11_390/AmazonDynamoDBClient_Instrumentation.java index 5b45d9372..c5b72f8f1 100644 --- a/instrumentation-security/dynamodb-1.11.390/src/main/java/com/amazonaws/services/dynamodbv2_1_11_390/AmazonDynamoDBClient_Instrumentation.java +++ b/instrumentation-security/dynamodb-1.11.390/src/main/java/com/amazonaws/services/dynamodbv2_1_11_390/AmazonDynamoDBClient_Instrumentation.java @@ -16,6 +16,7 @@ import com.amazonaws.http.ExecutionContext; import com.amazonaws.http.HttpResponseHandler; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import com.newrelic.agent.security.instrumentation.dynamodb_1_11_390.DynamoDBUtil; @@ -36,7 +37,7 @@ public AmazonDynamoDBClient_Instrumentation(ClientConfiguration clientConfigurat private Response doInvoke(Request request, HttpResponseHandler> responseHandler, ExecutionContext executionContext, URI discoveredEndpoint) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(request.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, request.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(request, this.getClass().getName()); } 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 2766ce945..66a2d18af 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 @@ -25,6 +25,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.helper.DynamoDBRequest; import com.newrelic.api.agent.security.schema.operation.DynamoDBOperation; @@ -94,9 +95,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/dynamodb-1.11.453/src/main/java/com/amazonaws/services/dynamodbv2_1_11_453/AmazonDynamoDBClient_Instrumentation.java b/instrumentation-security/dynamodb-1.11.453/src/main/java/com/amazonaws/services/dynamodbv2_1_11_453/AmazonDynamoDBClient_Instrumentation.java index 840b4ea9f..6b4e8153b 100644 --- a/instrumentation-security/dynamodb-1.11.453/src/main/java/com/amazonaws/services/dynamodbv2_1_11_453/AmazonDynamoDBClient_Instrumentation.java +++ b/instrumentation-security/dynamodb-1.11.453/src/main/java/com/amazonaws/services/dynamodbv2_1_11_453/AmazonDynamoDBClient_Instrumentation.java @@ -16,6 +16,7 @@ import com.amazonaws.http.ExecutionContext; import com.amazonaws.http.HttpResponseHandler; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import com.newrelic.agent.security.instrumentation.dynamodb_1_11_453.DynamoDBUtil; @@ -35,7 +36,7 @@ public AmazonDynamoDBClient_Instrumentation(ClientConfiguration clientConfigurat private Response doInvoke(Request request, HttpResponseHandler> responseHandler, ExecutionContext executionContext, URI discoveredEndpoint, URI uriFromEndpointTrait) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(request.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, request.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(request, this.getClass().getName()); } 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 d1d2bb4ac..0478947e0 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 @@ -25,6 +25,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.helper.DynamoDBRequest; import com.newrelic.api.agent.security.schema.operation.DynamoDBOperation; @@ -95,9 +96,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/dynamodb-1.11.459/src/main/java/com/amazonaws/services/dynamodbv2_1_11_459/AmazonDynamoDBClient_Instrumentation.java b/instrumentation-security/dynamodb-1.11.459/src/main/java/com/amazonaws/services/dynamodbv2_1_11_459/AmazonDynamoDBClient_Instrumentation.java index eece5aae0..dc82520ae 100644 --- a/instrumentation-security/dynamodb-1.11.459/src/main/java/com/amazonaws/services/dynamodbv2_1_11_459/AmazonDynamoDBClient_Instrumentation.java +++ b/instrumentation-security/dynamodb-1.11.459/src/main/java/com/amazonaws/services/dynamodbv2_1_11_459/AmazonDynamoDBClient_Instrumentation.java @@ -16,6 +16,7 @@ import com.amazonaws.http.ExecutionContext; import com.amazonaws.http.HttpResponseHandler; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import com.newrelic.agent.security.instrumentation.dynamodb_1_11_459.DynamoDBUtil; @@ -35,7 +36,7 @@ public AmazonDynamoDBClient_Instrumentation(ClientConfiguration clientConfigurat private Response doInvoke(Request request, HttpResponseHandler> responseHandler, ExecutionContext executionContext, URI discoveredEndpoint, URI uriFromEndpointTrait) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(request.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, request.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(request, this.getClass().getName()); } 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 352b50a1c..d981b6199 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 @@ -34,6 +34,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.helper.DynamoDBRequest; import com.newrelic.api.agent.security.schema.operation.DynamoDBOperation; @@ -104,9 +105,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/dynamodb-1.11.80/src/main/java/com/amazonaws/services/dynamodbv2_1_11_80/AmazonDynamoDBClient_Instrumentation.java b/instrumentation-security/dynamodb-1.11.80/src/main/java/com/amazonaws/services/dynamodbv2_1_11_80/AmazonDynamoDBClient_Instrumentation.java index 0464b2b1f..129f18b40 100644 --- a/instrumentation-security/dynamodb-1.11.80/src/main/java/com/amazonaws/services/dynamodbv2_1_11_80/AmazonDynamoDBClient_Instrumentation.java +++ b/instrumentation-security/dynamodb-1.11.80/src/main/java/com/amazonaws/services/dynamodbv2_1_11_80/AmazonDynamoDBClient_Instrumentation.java @@ -16,6 +16,7 @@ import com.amazonaws.http.ExecutionContext; import com.amazonaws.http.HttpResponseHandler; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import com.newrelic.agent.security.instrumentation.dynamodb_1_11_80.DynamoDBUtil; @@ -35,7 +36,7 @@ public AmazonDynamoDBClient_Instrumentation(ClientConfiguration clientConfigurat private Response doInvoke(Request request, HttpResponseHandler> responseHandler, ExecutionContext executionContext) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(request.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, request.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(request, this.getClass().getName()); } 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 13e1a39d8..44d708f95 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 @@ -25,6 +25,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.helper.DynamoDBRequest; import com.newrelic.api.agent.security.schema.operation.DynamoDBOperation; @@ -94,9 +95,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; 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 cab84ab53..1e59b670f 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 @@ -11,6 +11,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.helper.DynamoDBRequest; import com.newrelic.api.agent.security.schema.operation.DynamoDBOperation; @@ -96,7 +97,7 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { diff --git a/instrumentation-security/dynamodb-2.1.0/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java b/instrumentation-security/dynamodb-2.1.0/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java index 402aeac1b..f977f3aa9 100644 --- a/instrumentation-security/dynamodb-2.1.0/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java +++ b/instrumentation-security/dynamodb-2.1.0/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java @@ -8,6 +8,7 @@ package software.amazon.awssdk.core.client.handler; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -24,7 +25,7 @@ public class AsyncClientHandler_Instrumentation { public CompletableFuture execute( ClientExecutionParams executionParams) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } @@ -44,7 +45,7 @@ public Complet ClientExecutionParams executionParams, AsyncResponseTransformer asyncResponseTransformer) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } diff --git a/instrumentation-security/dynamodb-2.1.0/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java b/instrumentation-security/dynamodb-2.1.0/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java index 44c672ec0..412f6d137 100644 --- a/instrumentation-security/dynamodb-2.1.0/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java +++ b/instrumentation-security/dynamodb-2.1.0/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java @@ -8,6 +8,7 @@ package software.amazon.awssdk.core.client.handler; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -22,7 +23,7 @@ public class SyncClientHandler_Instrumentation { public OutputT execute( ClientExecutionParams executionParams) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } @@ -42,7 +43,7 @@ public ReturnT ClientExecutionParams executionParams, ResponseTransformer responseTransformer) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } 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 1f85651cc..73f8d5691 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 @@ -11,6 +11,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.helper.DynamoDBRequest; import com.newrelic.api.agent.security.schema.operation.DynamoDBOperation; @@ -105,9 +106,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/dynamodb-2.1.2/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java b/instrumentation-security/dynamodb-2.1.2/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java index 11de52c85..0543f2a75 100644 --- a/instrumentation-security/dynamodb-2.1.2/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java +++ b/instrumentation-security/dynamodb-2.1.2/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java @@ -9,10 +9,10 @@ import com.newrelic.agent.security.instrumentation.dynamodb_212.DynamoDBUtil; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; 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.dynamodb_212.DynamoDBUtil; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.async.AsyncResponseTransformer; @@ -25,7 +25,7 @@ public class AsyncClientHandler_Instrumentation { public CompletableFuture execute( ClientExecutionParams executionParams) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } @@ -45,7 +45,7 @@ public Complet ClientExecutionParams executionParams, AsyncResponseTransformer asyncResponseTransformer) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } diff --git a/instrumentation-security/dynamodb-2.1.2/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java b/instrumentation-security/dynamodb-2.1.2/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java index 5f2c86e2f..8762c91b2 100644 --- a/instrumentation-security/dynamodb-2.1.2/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java +++ b/instrumentation-security/dynamodb-2.1.2/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java @@ -9,10 +9,10 @@ import com.newrelic.agent.security.instrumentation.dynamodb_212.DynamoDBUtil; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; 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.dynamodb_212.DynamoDBUtil; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.sync.ResponseTransformer; @@ -23,7 +23,7 @@ public class SyncClientHandler_Instrumentation { public OutputT execute( ClientExecutionParams executionParams) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } @@ -43,7 +43,7 @@ public ReturnT ClientExecutionParams executionParams, ResponseTransformer responseTransformer) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } 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 2e26b9bbe..35c9cc87a 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 @@ -11,6 +11,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.helper.DynamoDBRequest; import com.newrelic.api.agent.security.schema.operation.DynamoDBOperation; @@ -110,9 +111,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/dynamodb-2.15.34/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java b/instrumentation-security/dynamodb-2.15.34/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java index 14c57f588..107928d21 100644 --- a/instrumentation-security/dynamodb-2.15.34/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java +++ b/instrumentation-security/dynamodb-2.15.34/src/main/java/software/amazon/awssdk/core/client/handler/AsyncClientHandler_Instrumentation.java @@ -9,10 +9,10 @@ import com.newrelic.agent.security.instrumentation.dynamodb_215.DynamoDBUtil; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; 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.dynamodb_215.DynamoDBUtil; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.async.AsyncResponseTransformer; @@ -25,7 +25,7 @@ public class AsyncClientHandler_Instrumentation { public CompletableFuture execute( ClientExecutionParams executionParams) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } @@ -45,7 +45,7 @@ public Complet ClientExecutionParams executionParams, AsyncResponseTransformer asyncResponseTransformer) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } diff --git a/instrumentation-security/dynamodb-2.15.34/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java b/instrumentation-security/dynamodb-2.15.34/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java index 5d38c0b9d..d312b10c5 100644 --- a/instrumentation-security/dynamodb-2.15.34/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java +++ b/instrumentation-security/dynamodb-2.15.34/src/main/java/software/amazon/awssdk/core/client/handler/SyncClientHandler_Instrumentation.java @@ -9,10 +9,10 @@ import com.newrelic.agent.security.instrumentation.dynamodb_215.DynamoDBUtil; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; 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.dynamodb_215.DynamoDBUtil; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.sync.ResponseTransformer; @@ -23,7 +23,7 @@ public class SyncClientHandler_Instrumentation { public OutputT execute( ClientExecutionParams executionParams) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } @@ -43,7 +43,7 @@ public ReturnT ClientExecutionParams executionParams, ResponseTransformer responseTransformer) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = DynamoDBUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = DynamoDBUtil.processDynamoDBRequest(executionParams, this.getClass().getName()); } diff --git a/instrumentation-security/file-low-priority-instrumentation/src/main/java/com/newrelic/agent/security/instrumentation/random/java/io/File_Instrumentation.java b/instrumentation-security/file-low-priority-instrumentation/src/main/java/com/newrelic/agent/security/instrumentation/random/java/io/File_Instrumentation.java index 44f8b3183..989790c66 100644 --- a/instrumentation-security/file-low-priority-instrumentation/src/main/java/com/newrelic/agent/security/instrumentation/random/java/io/File_Instrumentation.java +++ b/instrumentation-security/file-low-priority-instrumentation/src/main/java/com/newrelic/agent/security/instrumentation/random/java/io/File_Instrumentation.java @@ -5,6 +5,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.FileOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -22,7 +23,7 @@ public abstract class File_Instrumentation { public abstract String getAbsolutePath(); public boolean exists() { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); boolean isOwaspHookEnabled = NewRelicSecurity.getAgent().isLowPriorityInstrumentationEnabled(); AbstractOperation operation = null; @@ -43,19 +44,12 @@ public boolean exists() { return returnVal; } - private static boolean acquireFileLockIfPossible() { - try { - return FileHelper.acquireFileLockIfPossible(); - } catch (Throwable ignored) { - } - return false; + private static boolean acquireFileLockIfPossible(VulnerabilityCaseType fileOperation) { + return GenericHelper.acquireLockIfPossible(fileOperation, FileHelper.getNrSecCustomAttribName()); } private static void releaseFileLock() { - try { - FileHelper.releaseFileLock(); - } catch (Throwable ignored) { - } + GenericHelper.releaseLock(FileHelper.getNrSecCustomAttribName()); } diff --git a/instrumentation-security/file-operation/src/main/java/java/io/FileInputStream_Instrumentation.java b/instrumentation-security/file-operation/src/main/java/java/io/FileInputStream_Instrumentation.java index a4a9fb3cf..817531e2d 100644 --- a/instrumentation-security/file-operation/src/main/java/java/io/FileInputStream_Instrumentation.java +++ b/instrumentation-security/file-operation/src/main/java/java/io/FileInputStream_Instrumentation.java @@ -11,6 +11,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.FileHelper; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.FileOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -22,7 +23,7 @@ public abstract class FileInputStream_Instrumentation { private void open(String name) throws FileNotFoundException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(name); @@ -37,17 +38,12 @@ private void open(String name) throws FileNotFoundException { registerExitOperation(isFileLockAcquired, operation); } - private boolean acquireFileLockIfPossible() { - try { - return FileHelper.acquireFileLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private static boolean acquireFileLockIfPossible(VulnerabilityCaseType fileOperation) { + return GenericHelper.acquireLockIfPossible(fileOperation, FileHelper.getNrSecCustomAttribName()); } - private void releaseFileLock() { - try { - FileHelper.releaseFileLock(); - } catch (Throwable e) {} + private static void releaseFileLock() { + GenericHelper.releaseLock(FileHelper.getNrSecCustomAttribName()); } private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { diff --git a/instrumentation-security/file-operation/src/main/java/java/io/FileOutputStream_Instrumentation.java b/instrumentation-security/file-operation/src/main/java/java/io/FileOutputStream_Instrumentation.java index 1c9a794f5..ae6e2e885 100644 --- a/instrumentation-security/file-operation/src/main/java/java/io/FileOutputStream_Instrumentation.java +++ b/instrumentation-security/file-operation/src/main/java/java/io/FileOutputStream_Instrumentation.java @@ -11,6 +11,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.FileHelper; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.FileOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -23,7 +24,7 @@ public abstract class FileOutputStream_Instrumentation { private void open(String name, boolean append) throws FileNotFoundException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(name); @@ -38,17 +39,12 @@ private void open(String name, boolean append) registerExitOperation(isFileLockAcquired, operation); } - private boolean acquireFileLockIfPossible() { - try { - return FileHelper.acquireFileLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private static boolean acquireFileLockIfPossible(VulnerabilityCaseType fileOperation) { + return GenericHelper.acquireLockIfPossible(fileOperation, FileHelper.getNrSecCustomAttribName()); } - private void releaseFileLock() { - try { - FileHelper.releaseFileLock(); - } catch (Throwable e) {} + private static void releaseFileLock() { + GenericHelper.releaseLock(FileHelper.getNrSecCustomAttribName()); } private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { diff --git a/instrumentation-security/file-operation/src/main/java/java/io/File_Instrumentation.java b/instrumentation-security/file-operation/src/main/java/java/io/File_Instrumentation.java index 8a76fc621..6c7372d77 100644 --- a/instrumentation-security/file-operation/src/main/java/java/io/File_Instrumentation.java +++ b/instrumentation-security/file-operation/src/main/java/java/io/File_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.FileHelper; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.FileOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -18,7 +19,7 @@ public abstract class File_Instrumentation { public boolean createNewFile() throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_CREATE_NEW_FILE, false, this); @@ -36,7 +37,7 @@ public boolean createNewFile() throws IOException { } public boolean delete() { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_DELETE, false, this); @@ -54,7 +55,7 @@ public boolean delete() { } public void deleteOnExit() { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_DELETE_ON_EXIT, false, this); @@ -70,7 +71,7 @@ public void deleteOnExit() { } public String[] list() { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_LIST, false, this); @@ -88,7 +89,7 @@ public String[] list() { } public String[] list(FilenameFilter filter) { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_LIST, false, this); @@ -106,7 +107,7 @@ public String[] list(FilenameFilter filter) { } public File[] listFiles() { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_LISTFILES, false, this); @@ -124,7 +125,7 @@ public File[] listFiles() { } public File[] listFiles(FilenameFilter filter) { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_LISTFILES, false, this); @@ -142,7 +143,7 @@ public File[] listFiles(FilenameFilter filter) { } public File[] listFiles(FileFilter filter) { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_LISTFILES, false, this); @@ -160,7 +161,7 @@ public File[] listFiles(FileFilter filter) { } public boolean mkdir() { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_MKDIR, false, this); @@ -178,7 +179,7 @@ public boolean mkdir() { } public boolean mkdirs() { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_MKDIRS, false, this); @@ -196,7 +197,7 @@ public boolean mkdirs() { } public boolean renameTo(File_Instrumentation dest) { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_RENAME_TO, false, this, dest); @@ -214,7 +215,7 @@ public boolean renameTo(File_Instrumentation dest) { } public boolean setReadOnly() { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_SET_READ_ONLY, false, this); @@ -232,7 +233,7 @@ public boolean setReadOnly() { } public boolean setWritable(boolean writable, boolean ownerOnly) { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_SET_WRITABLE, false, this); @@ -250,7 +251,7 @@ public boolean setWritable(boolean writable, boolean ownerOnly) { } public boolean setWritable(boolean writable) { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_SET_WRITABLE, false, this); @@ -268,7 +269,7 @@ public boolean setWritable(boolean writable) { } public boolean setReadable(boolean readable, boolean ownerOnly) { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_SET_READABLE, false, this); @@ -286,7 +287,7 @@ public boolean setReadable(boolean readable, boolean ownerOnly) { } public boolean setReadable(boolean readable) { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_SET_READABLE, false, this); @@ -304,7 +305,7 @@ public boolean setReadable(boolean readable) { } public boolean setExecutable(boolean executable, boolean ownerOnly) { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_SET_EXECUTABLE, false, this); @@ -322,7 +323,7 @@ public boolean setExecutable(boolean executable, boolean ownerOnly) { } public boolean setExecutable(boolean executable) { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_SET_EXECUTABLE, false, this); @@ -345,19 +346,12 @@ public boolean setExecutable(boolean executable) { public abstract String getAbsolutePath(); - private static boolean acquireFileLockIfPossible() { - try { - return FileHelper.acquireFileLockIfPossible(); - } catch (Throwable ignored) { - } - return false; + private static boolean acquireFileLockIfPossible(VulnerabilityCaseType fileOperation) { + return GenericHelper.acquireLockIfPossible(fileOperation, FileHelper.getNrSecCustomAttribName()); } private static void releaseFileLock() { - try { - FileHelper.releaseFileLock(); - } catch (Throwable ignored) { - } + GenericHelper.releaseLock(FileHelper.getNrSecCustomAttribName()); } diff --git a/instrumentation-security/file-operation/src/main/java/java/io/RandomAccessFile_Instrumentation.java b/instrumentation-security/file-operation/src/main/java/java/io/RandomAccessFile_Instrumentation.java index 7f3760268..85517df32 100644 --- a/instrumentation-security/file-operation/src/main/java/java/io/RandomAccessFile_Instrumentation.java +++ b/instrumentation-security/file-operation/src/main/java/java/io/RandomAccessFile_Instrumentation.java @@ -11,6 +11,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.FileHelper; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.FileOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -22,7 +23,7 @@ public abstract class RandomAccessFile_Instrumentation { private void open(String name, int mode) throws FileNotFoundException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(name); @@ -37,17 +38,12 @@ private void open(String name, int mode) throws FileNotFoundException { registerExitOperation(isFileLockAcquired, operation); } - private boolean acquireFileLockIfPossible() { - try { - return FileHelper.acquireFileLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private static boolean acquireFileLockIfPossible(VulnerabilityCaseType fileOperation) { + return GenericHelper.acquireLockIfPossible(fileOperation, FileHelper.getNrSecCustomAttribName()); } - private void releaseFileLock() { - try { - FileHelper.releaseFileLock(); - } catch (Throwable e) {} + private static void releaseFileLock() { + GenericHelper.releaseLock(FileHelper.getNrSecCustomAttribName()); } private void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) { diff --git a/instrumentation-security/file-operation/src/main/java/java/nio/file/Files_Instrumentation.java b/instrumentation-security/file-operation/src/main/java/java/nio/file/Files_Instrumentation.java index 28181b03b..d2a88246b 100644 --- a/instrumentation-security/file-operation/src/main/java/java/nio/file/Files_Instrumentation.java +++ b/instrumentation-security/file-operation/src/main/java/java/nio/file/Files_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.FileHelper; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.FileOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -26,7 +27,7 @@ public static Path setPosixFilePermissions(Path path, Set perms) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if (isFileLockAcquired) { operation = preprocessSecurityHook(false, FileHelper.METHOD_NAME_SETPOSIXFILEPERMISSIONS, false, path.toFile()); @@ -43,19 +44,12 @@ public static Path setPosixFilePermissions(Path path, return returnVal; } - private static boolean acquireFileLockIfPossible() { - try { - return FileHelper.acquireFileLockIfPossible(); - } catch (Throwable ignored) { - } - return false; + private static boolean acquireFileLockIfPossible(VulnerabilityCaseType fileOperation) { + return GenericHelper.acquireLockIfPossible(fileOperation, FileHelper.getNrSecCustomAttribName()); } private static void releaseFileLock() { - try { - FileHelper.releaseFileLock(); - } catch (Throwable ignored) { - } + GenericHelper.releaseLock(FileHelper.getNrSecCustomAttribName()); } diff --git a/instrumentation-security/file-operation/src/main/java/java/nio/file/spi/FileSystemProvider_Instrumentation.java b/instrumentation-security/file-operation/src/main/java/java/nio/file/spi/FileSystemProvider_Instrumentation.java index 81db76b0a..36b95a300 100644 --- a/instrumentation-security/file-operation/src/main/java/java/nio/file/spi/FileSystemProvider_Instrumentation.java +++ b/instrumentation-security/file-operation/src/main/java/java/nio/file/spi/FileSystemProvider_Instrumentation.java @@ -11,6 +11,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.FileHelper; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.FileOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -37,7 +38,7 @@ public abstract class FileSystemProvider_Instrumentation { public void copy(Path source, Path target, CopyOption... options) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if(isFileLockAcquired) { operation = preprocessSecurityHook(FileHelper.FILE_COPY, source, target); @@ -55,7 +56,7 @@ public void copy(Path source, Path target, CopyOption... options) public InputStream newInputStream(Path path, OpenOption... options) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; InputStream returnData; if(isFileLockAcquired) { @@ -75,7 +76,7 @@ public InputStream newInputStream(Path path, OpenOption... options) public OutputStream newOutputStream(Path path, OpenOption... options) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; OutputStream returnData; if(isFileLockAcquired) { @@ -97,7 +98,7 @@ public FileChannel newFileChannel(Path path, FileAttribute... attrs) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; FileChannel returnData; if(isFileLockAcquired) { @@ -120,7 +121,7 @@ public AsynchronousFileChannel newAsynchronousFileChannel(Path path, FileAttribute... attrs) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; AsynchronousFileChannel returnData; if(isFileLockAcquired) { @@ -140,7 +141,7 @@ public AsynchronousFileChannel newAsynchronousFileChannel(Path path, public SeekableByteChannel newByteChannel(Path path, Set options, FileAttribute... attrs) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; SeekableByteChannel returnData; if(isFileLockAcquired) { @@ -159,7 +160,7 @@ public SeekableByteChannel newByteChannel(Path path, public DirectoryStream newDirectoryStream(Path dir, DirectoryStream.Filter filter) throws IOException{ - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; DirectoryStream returnData; if(isFileLockAcquired) { @@ -178,7 +179,7 @@ public DirectoryStream newDirectoryStream(Path dir, public void createDirectory(Path dir, FileAttribute... attrs) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if(isFileLockAcquired) { operation = preprocessSecurityHook(FileHelper.CREATE_DIRECTORY, dir); @@ -196,7 +197,7 @@ public void createDirectory(Path dir, FileAttribute... attrs) public void createSymbolicLink(Path link, Path target, FileAttribute... attrs) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if(isFileLockAcquired) { operation = preprocessSecurityHook(FileHelper.CREATE_SYMBOLIC_LINK, link, target); @@ -212,7 +213,7 @@ public void createSymbolicLink(Path link, Path target, FileAttribute... attrs } public void createLink(Path link, Path existing) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if(isFileLockAcquired) { operation = preprocessSecurityHook(FileHelper.CREATE_LINK, link, existing); @@ -228,7 +229,7 @@ public void createLink(Path link, Path existing) throws IOException { } public void delete(Path path) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if(isFileLockAcquired) { operation = preprocessSecurityHook(FileHelper.DELETE, path); @@ -244,7 +245,7 @@ public void delete(Path path) throws IOException { } public boolean deleteIfExists(Path path) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; boolean returnData; if(isFileLockAcquired) { @@ -263,7 +264,7 @@ public boolean deleteIfExists(Path path) throws IOException { public void move(Path source, Path target, CopyOption... options) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if(isFileLockAcquired) { operation = preprocessSecurityHook(FileHelper.MOVE, source, target); @@ -281,7 +282,7 @@ public void move(Path source, Path target, CopyOption... options) public void setAttribute(Path path, String attribute, Object value, LinkOption... options) throws IOException { - boolean isFileLockAcquired = acquireFileLockIfPossible(); + boolean isFileLockAcquired = acquireFileLockIfPossible(VulnerabilityCaseType.FILE_OPERATION); AbstractOperation operation = null; if(isFileLockAcquired) { operation = preprocessSecurityHook(FileHelper.SET_ATTRIBUTE, path); @@ -295,17 +296,13 @@ public void setAttribute(Path path, String attribute, } registerExitOperation(operation, isFileLockAcquired); } - private void releaseFileLock() { - try { - FileHelper.releaseFileLock(); - } catch (Throwable ignored){} + + private static boolean acquireFileLockIfPossible(VulnerabilityCaseType fileOperation) { + return GenericHelper.acquireLockIfPossible(fileOperation, FileHelper.getNrSecCustomAttribName()); } - private boolean acquireFileLockIfPossible() { - try { - return FileHelper.acquireFileLockIfPossible(); - } catch (Throwable ignored){} - return false; + private static void releaseFileLock() { + GenericHelper.releaseLock(FileHelper.getNrSecCustomAttribName()); } diff --git a/instrumentation-security/graalvm-jsinjection-19.0.0/src/main/java/com/oracle/truffle/polyglot/PolyglotContextImpl_Instrumentation.java b/instrumentation-security/graalvm-jsinjection-19.0.0/src/main/java/com/oracle/truffle/polyglot/PolyglotContextImpl_Instrumentation.java index 84d8f6bdf..7d7d7c6a4 100644 --- a/instrumentation-security/graalvm-jsinjection-19.0.0/src/main/java/com/oracle/truffle/polyglot/PolyglotContextImpl_Instrumentation.java +++ b/instrumentation-security/graalvm-jsinjection-19.0.0/src/main/java/com/oracle/truffle/polyglot/PolyglotContextImpl_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.JSInjectionOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -20,7 +21,7 @@ final class PolyglotContextImpl_Instrumentation { public Value eval(String languageId, Object sourceImpl) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.JAVASCRIPT_INJECTION); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(languageId, sourceImpl, JSEngineUtils.METHOD_EVAL); @@ -79,9 +80,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType javascriptInjection) { try { - return GenericHelper.acquireLockIfPossible(JSEngineUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(javascriptInjection, JSEngineUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/graalvm-jsinjection-22.0.0/src/main/java/com/oracle/truffle/polyglot/PolyglotContextImpl_Instrumentation.java b/instrumentation-security/graalvm-jsinjection-22.0.0/src/main/java/com/oracle/truffle/polyglot/PolyglotContextImpl_Instrumentation.java index 12ac4f31f..43a5cc51c 100644 --- a/instrumentation-security/graalvm-jsinjection-22.0.0/src/main/java/com/oracle/truffle/polyglot/PolyglotContextImpl_Instrumentation.java +++ b/instrumentation-security/graalvm-jsinjection-22.0.0/src/main/java/com/oracle/truffle/polyglot/PolyglotContextImpl_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.JSInjectionOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -20,7 +21,7 @@ final class PolyglotContextImpl_Instrumentation { public Value eval(String languageId, org.graalvm.polyglot.Source source) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.JAVASCRIPT_INJECTION); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(languageId, source, JSEngineUtils.METHOD_EVAL); @@ -78,9 +79,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType javascriptInjection) { try { - return GenericHelper.acquireLockIfPossible(JSEngineUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(javascriptInjection, JSEngineUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } 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 1733cca6e..fb120f290 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 @@ -6,6 +6,7 @@ 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.VulnerabilityCaseType; 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; @@ -67,34 +68,15 @@ public static AbstractOperation preprocessSecurityHook(String uri, Metadata meta public static void releaseLock() { - try { - if(NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttrName(), null); - } - } catch (Throwable ignored) { - } + GenericHelper.releaseLock(getNrSecCustomAttrName()); } private static String getNrSecCustomAttrName() { return GrpcClientUtils.NR_SEC_CUSTOM_ATTRIB_NAME+Thread.currentThread().getId(); } - public static boolean acquireLockIfPossible() { - try { - if (NewRelicSecurity.isHookProcessingActive() && - !isLockAcquired(getNrSecCustomAttrName())) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttrName(), true); - return true; - } - } catch (Throwable ignored){} - return false; + public static boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, getNrSecCustomAttrName()); } - private static boolean isLockAcquired(String nrSecCustomAttrName) { - try { - return NewRelicSecurity.isHookProcessingActive() && - Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(nrSecCustomAttrName, Boolean.class)); - } catch (Throwable ignored) {} - return false; - } } 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 bcd9e3388..6a0f04108 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 @@ -91,6 +91,9 @@ public static void preprocessSecurityHook(ServerStream_Instrumentat public static void postProcessSecurityHook(Metadata metadata, int statusCode, String className, String methodName) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } if (!NewRelicSecurity.isHookProcessingActive()) { return; } diff --git a/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/ClientCall_Instrumentation.java b/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/ClientCall_Instrumentation.java index 0291a1817..47f49a1f1 100644 --- a/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/ClientCall_Instrumentation.java +++ b/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/ClientCall_Instrumentation.java @@ -3,6 +3,7 @@ import com.newrelic.agent.security.instrumentation.grpc1220.GrpcClientUtils; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.NewField; @@ -20,7 +21,7 @@ public abstract class ClientCall_Instrumentation { MethodDescriptor methodDescriptor = null; public void start(ClientCall.Listener var1, Metadata var2) { - boolean isLockAcquired = GrpcClientUtils.acquireLockIfPossible(); + boolean isLockAcquired = GrpcClientUtils.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if (isLockAcquired) { 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 8e6adaee6..181f8f155 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 @@ -6,6 +6,7 @@ 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.VulnerabilityCaseType; 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; @@ -67,34 +68,14 @@ public static AbstractOperation preprocessSecurityHook(String uri, Metadata meta public static void releaseLock() { - try { - if(NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttrName(), null); - } - } catch (Throwable ignored) { - } + GenericHelper.releaseLock(getNrSecCustomAttrName()); } private static String getNrSecCustomAttrName() { return GrpcClientUtils.NR_SEC_CUSTOM_ATTRIB_NAME+Thread.currentThread().getId(); } - public static boolean acquireLockIfPossible() { - try { - if (NewRelicSecurity.isHookProcessingActive() && - !isLockAcquired(getNrSecCustomAttrName())) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttrName(), true); - return true; - } - } catch (Throwable ignored){} - return false; - } - - private static boolean isLockAcquired(String nrSecCustomAttrName) { - try { - return NewRelicSecurity.isHookProcessingActive() && - Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(nrSecCustomAttrName, Boolean.class)); - } catch (Throwable ignored) {} - return false; + public static boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, getNrSecCustomAttrName()); } } 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 4481b3f70..e4e9431d4 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 @@ -95,6 +95,9 @@ public static void preprocessSecurityHook(ServerStream_Instrumentat public static void postProcessSecurityHook(Metadata metadata, int statusCode, String className, String methodName) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } if (!NewRelicSecurity.isHookProcessingActive()) { return; } diff --git a/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/ClientCall_Instrumentation.java b/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/ClientCall_Instrumentation.java index ca4b45320..dd1b90d11 100644 --- a/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/ClientCall_Instrumentation.java +++ b/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/ClientCall_Instrumentation.java @@ -3,6 +3,7 @@ import com.newrelic.agent.security.instrumentation.grpc140.GrpcClientUtils; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.NewField; @@ -20,7 +21,7 @@ public abstract class ClientCall_Instrumentation { MethodDescriptor methodDescriptor = null; public void start(ClientCall.Listener var1, Metadata var2) { - boolean isLockAcquired = GrpcClientUtils.acquireLockIfPossible(); + boolean isLockAcquired = GrpcClientUtils.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if (isLockAcquired) { 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 30c9953b7..3145a0cad 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 @@ -6,6 +6,7 @@ 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.VulnerabilityCaseType; 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; @@ -67,33 +68,15 @@ public static AbstractOperation preprocessSecurityHook(String uri, Metadata meta public static void releaseLock() { - try { - if(NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttrName(), null); - } - } catch (Throwable ignored){} + GenericHelper.releaseLock(getNrSecCustomAttrName()); } private static String getNrSecCustomAttrName() { return GrpcClientUtils.NR_SEC_CUSTOM_ATTRIB_NAME+Thread.currentThread().getId(); } - public static boolean acquireLockIfPossible() { - try { - if (NewRelicSecurity.isHookProcessingActive() && - !isLockAcquired(getNrSecCustomAttrName())) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttrName(), true); - return true; - } - } catch (Throwable ignored){} - return false; + public static boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, getNrSecCustomAttrName()); } - private static boolean isLockAcquired(String nrSecCustomAttrName) { - try { - return NewRelicSecurity.isHookProcessingActive() && - Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(nrSecCustomAttrName, Boolean.class)); - } catch (Throwable ignored) {} - return false; - } } 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 441865d70..90cb822dd 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 @@ -90,6 +90,9 @@ public static void preprocessSecurityHook(ServerStream_Instrumentat public static void postProcessSecurityHook(Metadata metadata, int statusCode, String className, String methodName) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } if (!NewRelicSecurity.isHookProcessingActive()) { return; } diff --git a/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/ClientCall_Instrumentation.java b/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/ClientCall_Instrumentation.java index ebd0d6ec4..79ee376e0 100644 --- a/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/ClientCall_Instrumentation.java +++ b/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/ClientCall_Instrumentation.java @@ -3,6 +3,7 @@ import com.newrelic.agent.security.instrumentation.grpc1400.GrpcClientUtils; import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.NewField; @@ -20,7 +21,7 @@ public abstract class ClientCall_Instrumentation { MethodDescriptor csecMethodDescriptor = null; public void start(ClientCall.Listener var1, Metadata var2) { - boolean isLockAcquired = GrpcClientUtils.acquireLockIfPossible(); + boolean isLockAcquired = GrpcClientUtils.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if (isLockAcquired) { diff --git a/instrumentation-security/http-async-client-4/src/main/java/com/newrelic/agent/security/instrumentation/httpasyncclient4/HttpAsyncClient4_Instrumentation.java b/instrumentation-security/http-async-client-4/src/main/java/com/newrelic/agent/security/instrumentation/httpasyncclient4/HttpAsyncClient4_Instrumentation.java index 86ec258c6..63391d32a 100644 --- a/instrumentation-security/http-async-client-4/src/main/java/com/newrelic/agent/security/instrumentation/httpasyncclient4/HttpAsyncClient4_Instrumentation.java +++ b/instrumentation-security/http-async-client-4/src/main/java/com/newrelic/agent/security/instrumentation/httpasyncclient4/HttpAsyncClient4_Instrumentation.java @@ -13,6 +13,7 @@ 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.VulnerabilityCaseType; 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; @@ -39,7 +40,7 @@ public class HttpAsyncClient4_Instrumentation { public Future execute(HttpAsyncRequestProducer requestProducer, HttpAsyncResponseConsumer responseConsumer, HttpContext context, FutureCallback callback) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -65,7 +66,7 @@ public Future execute(HttpAsyncRequestProducer requestProducer, HttpAsync } public Future execute(HttpAsyncRequestProducer requestProducer, HttpAsyncResponseConsumer responseConsumer, FutureCallback callback) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -91,7 +92,7 @@ public Future execute(HttpAsyncRequestProducer requestProducer, HttpAsync } public Future execute(HttpHost target, HttpRequest request, HttpContext context, FutureCallback callback) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase @@ -119,7 +120,7 @@ public Future execute(HttpHost target, HttpRequest request, HttpCo } public Future execute(HttpHost target, HttpRequest request, FutureCallback callback) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase @@ -147,7 +148,7 @@ public Future execute(HttpHost target, HttpRequest request, Future } public Future execute(HttpUriRequest request, HttpContext context, FutureCallback callback) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -167,7 +168,7 @@ public Future execute(HttpUriRequest request, HttpContext context, } public Future execute(HttpUriRequest request, FutureCallback callback) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -255,9 +256,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { try { - return GenericHelper.acquireLockIfPossible(SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); + return GenericHelper.acquireLockIfPossible(httpRequest, SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/httpclient-3/src/main/java/com/newrelic/agent/security/instrumentation/httpclient3/HttpMethodBase_Instrumentation.java b/instrumentation-security/httpclient-3/src/main/java/com/newrelic/agent/security/instrumentation/httpclient3/HttpMethodBase_Instrumentation.java index 95745b0a5..785fae956 100644 --- a/instrumentation-security/httpclient-3/src/main/java/com/newrelic/agent/security/instrumentation/httpclient3/HttpMethodBase_Instrumentation.java +++ b/instrumentation-security/httpclient-3/src/main/java/com/newrelic/agent/security/instrumentation/httpclient3/HttpMethodBase_Instrumentation.java @@ -12,6 +12,7 @@ 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.VulnerabilityCaseType; 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; @@ -30,7 +31,7 @@ public abstract class HttpMethodBase_Instrumentation { public abstract void setRequestHeader(String headerName, String headerValue); public int execute(HttpState state, HttpConnection conn) throws HttpException, IOException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -150,9 +151,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { try { - return GenericHelper.acquireLockIfPossible(SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); + return GenericHelper.acquireLockIfPossible(httpRequest, SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/httpclient-4.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient40/HttpClient_Instrumentation.java b/instrumentation-security/httpclient-4.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient40/HttpClient_Instrumentation.java index 0eda0fb4b..c383b4007 100644 --- a/instrumentation-security/httpclient-4.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient40/HttpClient_Instrumentation.java +++ b/instrumentation-security/httpclient-4.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient40/HttpClient_Instrumentation.java @@ -13,6 +13,7 @@ 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.VulnerabilityCaseType; 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; @@ -34,7 +35,7 @@ public abstract class HttpClient_Instrumentation { public HttpResponse execute(HttpUriRequest request) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -54,7 +55,7 @@ public HttpResponse execute(HttpUriRequest request) throws Exception { } public HttpResponse execute(HttpUriRequest request, HttpContext context) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -74,7 +75,7 @@ public HttpResponse execute(HttpUriRequest request, HttpContext context) throws } public HttpResponse execute(HttpHost target, HttpRequest request) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase @@ -102,7 +103,7 @@ public HttpResponse execute(HttpHost target, HttpRequest request) throws Excepti } public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase @@ -131,7 +132,7 @@ public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext co public T execute(HttpUriRequest request, ResponseHandler responseHandler) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -152,7 +153,7 @@ public T execute(HttpUriRequest request, ResponseHandler res public T execute(HttpUriRequest request, ResponseHandler responseHandler, HttpContext context) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -173,7 +174,7 @@ public T execute(HttpUriRequest request, ResponseHandler res public T execute(HttpHost target, HttpRequest request, ResponseHandler responseHandler) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase @@ -202,7 +203,7 @@ public T execute(HttpHost target, HttpRequest request, Response public T execute(HttpHost target, HttpRequest request, ResponseHandler responseHandler, HttpContext context) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase @@ -304,9 +305,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { try { - return GenericHelper.acquireLockIfPossible(SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); + return GenericHelper.acquireLockIfPossible(httpRequest, SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/HttpAsyncClient_Instrumentation.java b/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/HttpAsyncClient_Instrumentation.java index b837e1e7c..8c0e601cb 100644 --- a/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/HttpAsyncClient_Instrumentation.java +++ b/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/HttpAsyncClient_Instrumentation.java @@ -10,6 +10,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -38,7 +39,7 @@ public Future execute( FutureCallback callback) { HttpRequest request = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(APACHE5_ASYNC_REQUEST_PRODUCER+requestProducer.hashCode(), HttpRequest.class); - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -68,9 +69,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { try { - return GenericHelper.acquireLockIfPossible(SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); + return GenericHelper.acquireLockIfPossible(httpRequest, SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/HttpClient_Instrumentation.java b/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/HttpClient_Instrumentation.java index d8358d594..e5b1a090c 100644 --- a/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/HttpClient_Instrumentation.java +++ b/instrumentation-security/httpclient-5.0/src/main/java/com/newrelic/agent/security/instrumentation/httpclient50/HttpClient_Instrumentation.java @@ -10,6 +10,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -29,7 +30,7 @@ public class HttpClient_Instrumentation { public HttpResponse execute(ClassicHttpRequest request) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -49,7 +50,7 @@ public HttpResponse execute(ClassicHttpRequest request) throws Exception { } public HttpResponse execute(ClassicHttpRequest request, HttpContext context) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -69,7 +70,7 @@ public HttpResponse execute(ClassicHttpRequest request, HttpContext context) thr } public ClassicHttpResponse execute(HttpHost target, ClassicHttpRequest request) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -95,7 +96,7 @@ public ClassicHttpResponse execute(HttpHost target, ClassicHttpRequest request) } public HttpResponse execute(HttpHost target, ClassicHttpRequest request, HttpContext context) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -122,7 +123,7 @@ public HttpResponse execute(HttpHost target, ClassicHttpRequest request, HttpCon public T execute(ClassicHttpRequest request, HttpClientResponseHandler responseHandler) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -143,7 +144,7 @@ public T execute(ClassicHttpRequest request, HttpClientResponseHandler T execute(ClassicHttpRequest request, HttpContext context, HttpClientResponseHandler responseHandler) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -164,7 +165,7 @@ public T execute(ClassicHttpRequest request, HttpContext context, HttpClient public T execute(HttpHost target, ClassicHttpRequest request, HttpClientResponseHandler responseHandler) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -191,7 +192,7 @@ public T execute(HttpHost target, ClassicHttpRequest request, HttpClientResp public T execute(HttpHost target, ClassicHttpRequest request, HttpContext context, HttpClientResponseHandler responseHandler) throws Exception { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -229,9 +230,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { try { - return GenericHelper.acquireLockIfPossible(SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); + return GenericHelper.acquireLockIfPossible(httpRequest, SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/httpclient-jdk11/src/main/java/com/newrelic/agent/security/instrumentation/http/HttpClientImpl_Instrumentation.java b/instrumentation-security/httpclient-jdk11/src/main/java/com/newrelic/agent/security/instrumentation/http/HttpClientImpl_Instrumentation.java index d7d163f48..a86fa1c53 100644 --- a/instrumentation-security/httpclient-jdk11/src/main/java/com/newrelic/agent/security/instrumentation/http/HttpClientImpl_Instrumentation.java +++ b/instrumentation-security/httpclient-jdk11/src/main/java/com/newrelic/agent/security/instrumentation/http/HttpClientImpl_Instrumentation.java @@ -8,6 +8,7 @@ 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.VulnerabilityCaseType; 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; @@ -38,7 +39,7 @@ private static void registerExitOperation(boolean isProcessingAllowed, AbstractO @Trace private CompletableFuture> sendAsync(HttpRequest request, HttpResponse.BodyHandler responseHandler, HttpResponse.PushPromiseHandler pushPromiseHandler, Executor exchangeExecutor) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; // Preprocess Phase if (isLockAcquired) { @@ -91,9 +92,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { try { - return GenericHelper.acquireLockIfPossible(SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); + return GenericHelper.acquireLockIfPossible(httpRequest, SecurityHelper.NR_SEC_CUSTOM_ATTRIB_NAME, this.hashCode()); } catch (Throwable ignored) { } return false; 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 507e695cd..ded02cd36 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 @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.utils.UserDataTranslationHelper; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -18,7 +19,7 @@ public abstract class Context_Instrumentation { public Object lookup(Name name) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); List operations = null; if(isLockAcquired) { operations = preprocessSecurityHook(name.getAll(), JNDIUtils.METHOD_LOOKUP); @@ -36,7 +37,7 @@ public Object lookup(Name name) throws NamingException { } public Object lookupLink(Name name) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); List operations = null; if(isLockAcquired) { operations = preprocessSecurityHook(name.getAll(), JNDIUtils.METHOD_LOOKUP); @@ -54,7 +55,7 @@ public Object lookupLink(Name name) throws NamingException { } public Object lookup(String name) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(name, JNDIUtils.METHOD_LOOKUP); @@ -72,7 +73,7 @@ public Object lookup(String name) throws NamingException { } public Object lookupLink(String name) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(name, JNDIUtils.METHOD_LOOKUP); @@ -163,9 +164,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType ldap) { try { - return GenericHelper.acquireLockIfPossible(JNDIUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(ldap, JNDIUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } 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 a2f263627..927e7eb32 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 @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.LDAPOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -20,7 +21,7 @@ public abstract class DirContext_Instrumentation implements Context { public NamingEnumeration search(Name name, String filterExpr, Object[] filterArgs, SearchControls cons) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if (isLockAcquired) { operation = preprocessSecurityHook(name.toString(), filterExpr); @@ -39,7 +40,7 @@ public NamingEnumeration search(Name name, String filterExpr, Obje } public NamingEnumeration search(String name, String filterExpr, Object[] filterArgs, SearchControls cons) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if (isLockAcquired) { operation = preprocessSecurityHook(name, filterExpr); @@ -58,7 +59,7 @@ public NamingEnumeration search(String name, String filterExpr, Ob } public NamingEnumeration search(String name, String filter, SearchControls cons) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if (isLockAcquired) { operation = preprocessSecurityHook(name, filter); @@ -82,7 +83,7 @@ public NamingEnumeration search(String name, String filter, Search SearchControls cons) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(name.toString(), filter); @@ -139,9 +140,9 @@ private void releaseLock() { } } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType ldap) { try { - return GenericHelper.acquireLockIfPossible(LDAPUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(ldap, LDAPUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) { } return false; 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 777896065..72e3f93cf 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 @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.XPathOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -22,7 +23,7 @@ public XObject execute( XPathContext xctxt, int contextNode, PrefixResolver namespaceContext) throws javax.xml.transform.TransformerException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(getPatternString(), "execute"); @@ -45,7 +46,7 @@ public XObject execute( PrefixResolver namespaceContext) throws javax.xml.transform.TransformerException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(getPatternString(), "execute"); @@ -101,9 +102,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType xpath) { try { - return GenericHelper.acquireLockIfPossible("XPATH_OPERATION_LOCK_JAVAXPATH-"); + return GenericHelper.acquireLockIfPossible(xpath, "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 ce65bb97b..714cf3cba 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 @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.XPathOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -19,7 +20,7 @@ public abstract class XPath_Instrumentation { public String evaluate(String expression, InputSource source) throws XPathExpressionException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(expression, "evaluate"); @@ -42,7 +43,7 @@ public Object evaluate( InputSource source, QName returnType) throws XPathExpressionException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(expression, "evaluate"); @@ -62,7 +63,7 @@ public Object evaluate( public String evaluate(String expression, Object item) throws XPathExpressionException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(expression, "evaluate"); @@ -82,7 +83,7 @@ public String evaluate(String expression, Object item) public Object evaluate(String expression, Object item, QName returnType) throws XPathExpressionException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(expression, "evaluate"); @@ -140,9 +141,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType xpath) { try { - return GenericHelper.acquireLockIfPossible("XPATH_OPERATION_LOCK_JAVAXPATH-"); + return GenericHelper.acquireLockIfPossible(xpath, "XPATH_OPERATION_LOCK_JAVAXPATH-"); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/jaxen-xpath-1.1/src/main/java/org/jaxen/BaseXPath_Instrumentation.java b/instrumentation-security/jaxen-xpath-1.1/src/main/java/org/jaxen/BaseXPath_Instrumentation.java index 591b15f90..6b837641e 100644 --- a/instrumentation-security/jaxen-xpath-1.1/src/main/java/org/jaxen/BaseXPath_Instrumentation.java +++ b/instrumentation-security/jaxen-xpath-1.1/src/main/java/org/jaxen/BaseXPath_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.XPathOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -20,7 +21,7 @@ public abstract class BaseXPath_Instrumentation { private String exprText = Weaver.callOriginal(); public List selectNodes(Object node) throws JaxenException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(this.exprText, XPATHUtils.METHOD_SELECT_NODES); @@ -78,9 +79,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType xpath) { try { - return GenericHelper.acquireLockIfPossible(XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(xpath, XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/jaxen-xpath/src/main/java/org/jaxen/BaseXPath_Instrumentation.java b/instrumentation-security/jaxen-xpath/src/main/java/org/jaxen/BaseXPath_Instrumentation.java index 94e9edf9b..2a0ec1af5 100644 --- a/instrumentation-security/jaxen-xpath/src/main/java/org/jaxen/BaseXPath_Instrumentation.java +++ b/instrumentation-security/jaxen-xpath/src/main/java/org/jaxen/BaseXPath_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.XPathOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -20,7 +21,7 @@ public abstract class BaseXPath_Instrumentation { private final String exprText = Weaver.callOriginal(); public List selectNodes(Object node) throws JaxenException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(this.exprText, XPATHUtils.METHOD_SELECT_NODES); @@ -78,9 +79,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType xpath) { try { - return GenericHelper.acquireLockIfPossible(XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(xpath, XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/jcache-1.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jcache_1_0_0/JCacheHelper.java b/instrumentation-security/jcache-1.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jcache_1_0_0/JCacheHelper.java index b2c2fb6ae..d813bcff0 100644 --- a/instrumentation-security/jcache-1.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jcache_1_0_0/JCacheHelper.java +++ b/instrumentation-security/jcache-1.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jcache_1_0_0/JCacheHelper.java @@ -3,6 +3,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.JCacheOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -54,9 +55,9 @@ public static void releaseLock(int hashcode) { } catch (Throwable ignored) {} } - public static boolean acquireLockIfPossible(int hashcode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType cachingDataStore, int hashcode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashcode); + return GenericHelper.acquireLockIfPossible(cachingDataStore, NR_SEC_CUSTOM_ATTRIB_NAME, hashcode); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/jcache-1.0.0/src/main/java/javax/cache/Cache_Instrumentation.java b/instrumentation-security/jcache-1.0.0/src/main/java/javax/cache/Cache_Instrumentation.java index 76f6a94f5..6672ebfed 100644 --- a/instrumentation-security/jcache-1.0.0/src/main/java/javax/cache/Cache_Instrumentation.java +++ b/instrumentation-security/jcache-1.0.0/src/main/java/javax/cache/Cache_Instrumentation.java @@ -2,6 +2,7 @@ import com.newrelic.agent.security.instrumentation.jcache_1_0_0.JCacheHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -17,7 +18,7 @@ @Weave(type = MatchType.Interface, originalName = "javax.cache.Cache") public abstract class Cache_Instrumentation { public V get(K key) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.READ, Collections.singletonList(key), this.getClass().getName(), "get"); @@ -35,7 +36,7 @@ public V get(K key) { } public Map getAll(Set keys) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.READ, new ArrayList() { { addAll(keys); } }, this.getClass().getName(), "getAll"); @@ -53,7 +54,7 @@ public Map getAll(Set keys) { } public boolean containsKey(K key) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.READ, Collections.singletonList(key), this.getClass().getName(), "containsKey"); @@ -71,7 +72,7 @@ public boolean containsKey(K key) { } public void loadAll(Set keys, boolean replaceExistingValues, CompletionListener completionListener) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.READ, new ArrayList() { { addAll(keys); } }, this.getClass().getName(), "loadAll"); @@ -87,7 +88,7 @@ public void loadAll(Set keys, boolean replaceExistingValues, Comple } public void put(K key, V value) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.WRITE, Arrays.asList(key, value), this.getClass().getName(), "put"); @@ -103,7 +104,7 @@ public void put(K key, V value) { } public V getAndPut(K key, V value) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.WRITE, Arrays.asList(key, value), this.getClass().getName(), "getAndPut"); @@ -121,7 +122,7 @@ public V getAndPut(K key, V value) { } public void putAll(Map map) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { List argList = new ArrayList<>(); @@ -143,7 +144,7 @@ public void putAll(Map map) { } public boolean putIfAbsent(K key, V value) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.WRITE, Arrays.asList(key, value), this.getClass().getName(), "putIfAbsent"); @@ -161,7 +162,7 @@ public boolean putIfAbsent(K key, V value) { } public boolean remove(K key) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.DELETE, Collections.singletonList(key), this.getClass().getName(), "remove"); @@ -179,7 +180,7 @@ public boolean remove(K key) { } public boolean remove(K key, V oldValue) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.DELETE, Arrays.asList(key, oldValue), this.getClass().getName(), "remove"); @@ -197,7 +198,7 @@ public boolean remove(K key, V oldValue) { } public V getAndRemove(K key) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.DELETE, Collections.singletonList(key), this.getClass().getName(), "getAndRemove"); @@ -215,7 +216,7 @@ public V getAndRemove(K key) { } public boolean replace(K key, V oldValue) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.UPDATE, Arrays.asList(key, oldValue), this.getClass().getName(), "replace"); @@ -233,7 +234,7 @@ public boolean replace(K key, V oldValue) { } public boolean replace(K key, V oldValue, V newValue) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.UPDATE, Arrays.asList(key, oldValue, newValue), this.getClass().getName(), "replace"); @@ -251,7 +252,7 @@ public boolean replace(K key, V oldValue, V newValue) { } public V getAndReplace(K key, V value) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.UPDATE, Arrays.asList(key, value), this.getClass().getName(), "getAndReplace"); @@ -269,7 +270,7 @@ public V getAndReplace(K key, V value) { } public void removeAll(Set keys) { - boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = JCacheHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, this.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = JCacheHelper.preprocessSecurityHook(JCacheHelper.DELETE, new ArrayList() { { addAll(keys); } }, this.getClass().getName(), "removeAll"); 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 083fc98da..3fdb82046 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 @@ -12,6 +12,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.JdbcHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.JDBCVendor; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.BatchSQLOperation; import com.newrelic.api.agent.security.schema.operation.SQLOperation; @@ -96,20 +97,15 @@ private AbstractOperation preprocessSecurityHook (String sql, String methodName) } private void releaseLock() { - try { - JdbcHelper.releaseLock(); - } catch (Throwable ignored) {} + GenericHelper.releaseLock(JdbcHelper.getNrSecCustomAttribName()); } - private boolean acquireLockIfPossible() { - try { - return JdbcHelper.acquireLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private boolean acquireLockIfPossible(VulnerabilityCaseType sqlDbCommand) { + return GenericHelper.acquireLockIfPossible(sqlDbCommand, JdbcHelper.getNrSecCustomAttribName()); } public ResultSet executeQuery() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { if(preparedSql == null){ @@ -130,7 +126,7 @@ public ResultSet executeQuery() throws SQLException { } public int executeUpdate() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { if(preparedSql == null){ @@ -151,7 +147,7 @@ public int executeUpdate() throws SQLException { } public boolean execute() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { if(preparedSql == null){ @@ -395,7 +391,7 @@ private void setObjectParams(int index, Object data) { objectParams.put(String.valueOf(index), data); } public void addBatch() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); SQLOperation sqlOperation = null; if(isLockAcquired) { sqlOperation = new SQLOperation(this.getClass().getName(), JdbcHelper.METHOD_EXECUTE_BATCH); diff --git a/instrumentation-security/jdbc-generic/src/main/java/java/sql/Statement_Instrumentation.java b/instrumentation-security/jdbc-generic/src/main/java/java/sql/Statement_Instrumentation.java index 2afc4310b..188de5713 100644 --- a/instrumentation-security/jdbc-generic/src/main/java/java/sql/Statement_Instrumentation.java +++ b/instrumentation-security/jdbc-generic/src/main/java/java/sql/Statement_Instrumentation.java @@ -12,6 +12,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.JdbcHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.JDBCVendor; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.BatchSQLOperation; import com.newrelic.api.agent.security.schema.operation.SQLOperation; @@ -104,7 +105,7 @@ private AbstractOperation preprocessSecurityHook(BatchSQLOperation operation){ public ResultSet executeQuery(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_QUERY); @@ -122,20 +123,15 @@ public ResultSet executeQuery(String sql) throws SQLException { } private void releaseLock() { - try { - JdbcHelper.releaseLock(); - } catch (Throwable ignored) {} + GenericHelper.releaseLock(JdbcHelper.getNrSecCustomAttribName()); } - private boolean acquireLockIfPossible() { - try { - return JdbcHelper.acquireLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private boolean acquireLockIfPossible(VulnerabilityCaseType sqlDbCommand) { + return GenericHelper.acquireLockIfPossible(sqlDbCommand, JdbcHelper.getNrSecCustomAttribName()); } public int executeUpdate(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -153,7 +149,7 @@ public int executeUpdate(String sql) throws SQLException { } public boolean execute(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); @@ -171,7 +167,7 @@ public boolean execute(String sql) throws SQLException { } public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -189,7 +185,7 @@ public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException } public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -207,7 +203,7 @@ public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { } public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); @@ -225,7 +221,7 @@ public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { } public int executeUpdate(String sql, String[] columnNames) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -243,7 +239,7 @@ public int executeUpdate(String sql, String[] columnNames) throws SQLException { } public boolean execute(String sql, String[] columnNames) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); @@ -261,7 +257,7 @@ public boolean execute(String sql, String[] columnNames) throws SQLException { } public boolean execute(String sql, int[] columnIndexes) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); @@ -279,7 +275,7 @@ public boolean execute(String sql, int[] columnIndexes) throws SQLException { } public void addBatch(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); SQLOperation sqlOperation = null; if(isLockAcquired) { sqlOperation = new SQLOperation(this.getClass().getName(), JdbcHelper.METHOD_EXECUTE_BATCH); @@ -301,7 +297,7 @@ public void addBatch(String sql) throws SQLException { } public void clearBatch() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); if(isLockAcquired) { if (batchSQLOperation==null){ batchSQLOperation = NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(JdbcHelper.NR_SEC_CUSTOM_ATTRIB_BATCH_SQL_NAME+hashCode(), BatchSQLOperation.class); @@ -320,7 +316,7 @@ public void clearBatch() throws SQLException { } public int[] executeBatch() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { if(batchSQLOperation==null|| batchSQLOperation.isEmpty()){ diff --git a/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsPreparedStatement_Instrumentation.java b/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsPreparedStatement_Instrumentation.java index 7c679301f..4c41e222d 100644 --- a/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsPreparedStatement_Instrumentation.java +++ b/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsPreparedStatement_Instrumentation.java @@ -13,6 +13,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.JdbcHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.JDBCVendor; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SQLOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -78,16 +79,13 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { - try { - return JdbcHelper.acquireLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private boolean acquireLockIfPossible(VulnerabilityCaseType sqlDbCommand) { + return GenericHelper.acquireLockIfPossible(sqlDbCommand, JdbcHelper.getNrSecCustomAttribName()); } @Trace(leaf = true) public ResultSet executeQuery() { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, getParameterValues(), JdbcHelper.METHOD_EXECUTE_QUERY); @@ -106,7 +104,7 @@ public ResultSet executeQuery() { @Trace(leaf = true) public int executeUpdate() { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, getParameterValues(), JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -125,7 +123,7 @@ public int executeUpdate() { @Trace(leaf = true) public boolean execute() { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, getParameterValues(), JdbcHelper.METHOD_EXECUTE); diff --git a/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsStatement_Instrumentation.java b/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsStatement_Instrumentation.java index 804f6a98c..c2f9dc4ee 100644 --- a/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsStatement_Instrumentation.java +++ b/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsStatement_Instrumentation.java @@ -12,6 +12,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.JdbcHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.JDBCVendor; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SQLOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -69,15 +70,12 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { - try { - return JdbcHelper.acquireLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, JdbcHelper.getNrSecCustomAttribName()); } public ResultSet executeQuery(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_QUERY); @@ -95,7 +93,7 @@ public ResultSet executeQuery(String sql) throws SQLException { } public int executeUpdate(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -113,7 +111,7 @@ public int executeUpdate(String sql) throws SQLException { } public boolean execute(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); @@ -131,7 +129,7 @@ public boolean execute(String sql) throws SQLException { } public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -150,7 +148,7 @@ public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -168,7 +166,7 @@ public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { } public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); @@ -186,7 +184,7 @@ public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { } public int executeUpdate(String sql, String[] columnNames) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -204,7 +202,7 @@ public int executeUpdate(String sql, String[] columnNames) throws SQLException { } public boolean execute(String sql, String[] columnNames) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); @@ -223,7 +221,7 @@ public boolean execute(String sql, String[] columnNames) throws SQLException { public boolean execute(String sql, int[] columnIndexes) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); diff --git a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/main/java/org/postgresql/jdbc2/AbstractJdbc2Statement_Instrumentation.java b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/main/java/org/postgresql/jdbc2/AbstractJdbc2Statement_Instrumentation.java index 49794b9f2..ba493bac3 100644 --- a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/main/java/org/postgresql/jdbc2/AbstractJdbc2Statement_Instrumentation.java +++ b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/main/java/org/postgresql/jdbc2/AbstractJdbc2Statement_Instrumentation.java @@ -12,6 +12,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.JdbcHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.JDBCVendor; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SQLOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -73,16 +74,11 @@ private AbstractOperation preprocessSecurityHook (String sql, String methodName) } private void releaseLock() { - try { - JdbcHelper.releaseLock(); - } catch (Throwable ignored) {} + GenericHelper.releaseLock(JdbcHelper.getNrSecCustomAttribName()); } - private boolean acquireLockIfPossible() { - try { - return JdbcHelper.acquireLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, JdbcHelper.getNrSecCustomAttribName()); } public AbstractJdbc2Statement_Instrumentation(AbstractJdbc2Connection connection, String sql, boolean isCallable, int rsType, int rsConcurrency) throws SQLException { @@ -90,7 +86,7 @@ public AbstractJdbc2Statement_Instrumentation(AbstractJdbc2Connection connection } public ResultSet executeQuery() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -111,7 +107,7 @@ public ResultSet executeQuery() throws SQLException { } public ResultSet executeQuery(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_QUERY); @@ -129,7 +125,7 @@ public ResultSet executeQuery(String sql) throws SQLException { } public int executeUpdate() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -150,7 +146,7 @@ public int executeUpdate() throws SQLException { } public int executeUpdate(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -168,7 +164,7 @@ public int executeUpdate(String sql) throws SQLException { } public boolean execute() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -189,7 +185,7 @@ public boolean execute() throws SQLException { } public boolean execute(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); diff --git a/instrumentation-security/jdbc-postgresql-9.4.1207/src/main/java/org/postgresql/jdbc/PgStatement_Instrumentation.java b/instrumentation-security/jdbc-postgresql-9.4.1207/src/main/java/org/postgresql/jdbc/PgStatement_Instrumentation.java index 588943d68..f27cb4069 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1207/src/main/java/org/postgresql/jdbc/PgStatement_Instrumentation.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1207/src/main/java/org/postgresql/jdbc/PgStatement_Instrumentation.java @@ -13,6 +13,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.JdbcHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.JDBCVendor; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SQLOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -83,15 +84,12 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { - try { - return JdbcHelper.acquireLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, JdbcHelper.getNrSecCustomAttribName()); } public ResultSet executeQuery() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -112,7 +110,7 @@ public ResultSet executeQuery() throws SQLException { } public ResultSet executeQuery(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_QUERY); @@ -130,7 +128,7 @@ public ResultSet executeQuery(String sql) throws SQLException { } public int executeUpdate() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -151,7 +149,7 @@ public int executeUpdate() throws SQLException { } public int executeUpdate(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -169,7 +167,7 @@ public int executeUpdate(String sql) throws SQLException { } public boolean execute() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -191,7 +189,7 @@ public boolean execute() throws SQLException { @Trace(leaf = true) public boolean execute(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); diff --git a/instrumentation-security/jedis-2.7.1_2.7.2/src/main/java/com/newrelic/agent/security/instrumentation/jedis_2_7_1/JedisHelper.java b/instrumentation-security/jedis-2.7.1_2.7.2/src/main/java/com/newrelic/agent/security/instrumentation/jedis_2_7_1/JedisHelper.java index 54e1d0bf9..d78ef528b 100644 --- a/instrumentation-security/jedis-2.7.1_2.7.2/src/main/java/com/newrelic/agent/security/instrumentation/jedis_2_7_1/JedisHelper.java +++ b/instrumentation-security/jedis-2.7.1_2.7.2/src/main/java/com/newrelic/agent/security/instrumentation/jedis_2_7_1/JedisHelper.java @@ -3,6 +3,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.RedisOperation; @@ -43,9 +44,9 @@ public static void releaseLock(int hashCode) { } catch (Throwable ignored) {} } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType cachingDataStore, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_LOCK_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(cachingDataStore, NR_SEC_LOCK_ATTRIB_NAME, hashCode); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/jedis-2.7.1_2.7.2/src/main/java/redis/clients/jedis/Connection_Instrumentation.java b/instrumentation-security/jedis-2.7.1_2.7.2/src/main/java/redis/clients/jedis/Connection_Instrumentation.java index 52f2b9f13..f889ad322 100644 --- a/instrumentation-security/jedis-2.7.1_2.7.2/src/main/java/redis/clients/jedis/Connection_Instrumentation.java +++ b/instrumentation-security/jedis-2.7.1_2.7.2/src/main/java/redis/clients/jedis/Connection_Instrumentation.java @@ -4,6 +4,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -18,7 +19,7 @@ @Weave(type = MatchType.BaseClass, originalName = "redis.clients.jedis.Connection") public abstract class Connection_Instrumentation { protected Connection sendCommand(final ProtocolCommand cmd, final byte[]... args) { - boolean isLockAcquired = JedisHelper.acquireLockIfPossible(cmd.hashCode()); + boolean isLockAcquired = JedisHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, cmd.hashCode()); AbstractOperation operation = null; if(isLockAcquired && cmd!=null && args!=null) { List argList = new ArrayList<>(); diff --git a/instrumentation-security/jedis-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jedis_3_0_0/JedisHelper.java b/instrumentation-security/jedis-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jedis_3_0_0/JedisHelper.java index 0c1582c19..0b1b7983f 100644 --- a/instrumentation-security/jedis-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jedis_3_0_0/JedisHelper.java +++ b/instrumentation-security/jedis-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jedis_3_0_0/JedisHelper.java @@ -3,6 +3,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.RedisOperation; @@ -43,9 +44,9 @@ public static void releaseLock(int hashCode) { } catch (Throwable ignored) {} } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType cachingDataStore, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_LOCK_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(cachingDataStore, NR_SEC_LOCK_ATTRIB_NAME, hashCode); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/jedis-3.0.0/src/main/java/redis/clients/jedis/Connection_Instrumentation.java b/instrumentation-security/jedis-3.0.0/src/main/java/redis/clients/jedis/Connection_Instrumentation.java index bf5e48f1b..466e71c8b 100644 --- a/instrumentation-security/jedis-3.0.0/src/main/java/redis/clients/jedis/Connection_Instrumentation.java +++ b/instrumentation-security/jedis-3.0.0/src/main/java/redis/clients/jedis/Connection_Instrumentation.java @@ -4,6 +4,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -19,7 +20,7 @@ @Weave(type = MatchType.BaseClass, originalName = "redis.clients.jedis.Connection") public abstract class Connection_Instrumentation { public void sendCommand(final ProtocolCommand cmd, final byte[]... args) { - boolean isLockAcquired = JedisHelper.acquireLockIfPossible(cmd.hashCode()); + boolean isLockAcquired = JedisHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, cmd.hashCode()); AbstractOperation operation = null; if(isLockAcquired && args != null && args.length > 0) { // args.length>0 will ensure the event generation for the commands with data List argList = new ArrayList<>(); diff --git a/instrumentation-security/jedis-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jedis_4_0_0/JedisHelper.java b/instrumentation-security/jedis-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jedis_4_0_0/JedisHelper.java index e0c30b3e4..ddc00efb2 100644 --- a/instrumentation-security/jedis-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jedis_4_0_0/JedisHelper.java +++ b/instrumentation-security/jedis-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/jedis_4_0_0/JedisHelper.java @@ -3,6 +3,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.RedisOperation; @@ -43,9 +44,9 @@ public static void releaseLock(int hashCode) { } catch (Throwable ignored) {} } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType cachingDataStore, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_LOCK_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(cachingDataStore, NR_SEC_LOCK_ATTRIB_NAME, hashCode); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/jedis-4.0.0/src/main/java/redis/clients/jedis/Connection_Instrumentation.java b/instrumentation-security/jedis-4.0.0/src/main/java/redis/clients/jedis/Connection_Instrumentation.java index 1c9b94479..c37936eac 100644 --- a/instrumentation-security/jedis-4.0.0/src/main/java/redis/clients/jedis/Connection_Instrumentation.java +++ b/instrumentation-security/jedis-4.0.0/src/main/java/redis/clients/jedis/Connection_Instrumentation.java @@ -4,6 +4,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -17,7 +18,7 @@ @Weave(type = MatchType.BaseClass, originalName = "redis.clients.jedis.Connection") public abstract class Connection_Instrumentation { public void sendCommand(final CommandArguments args) { - boolean isLockAcquired = JedisHelper.acquireLockIfPossible(args.hashCode()); + boolean isLockAcquired = JedisHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, args.hashCode()); AbstractOperation operation = null; if(isLockAcquired && args.size()>1) { // args.size()>1 will ensure the event generation for the commands with data String command = ""; diff --git a/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java b/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java index bde87f683..0718f51b8 100644 --- a/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java +++ b/instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java @@ -10,6 +10,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weaver; import org.glassfish.jersey.message.internal.OutboundJaxrsResponse; @@ -43,7 +44,7 @@ public abstract class ContainerResponse_Instrumentation { public void close() { boolean isLockAcquired = false; try { - isLockAcquired = GenericHelper.acquireLockIfPossible(SERVLET_GET_IS_OPERATION_LOCK); + isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK); if(isLockAcquired) { HttpRequestHelper.postProcessSecurityHook(this.getClass().getName(), getWrappedMessageContext()); } diff --git a/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java b/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java index a0593e5e3..f1f898aa3 100644 --- a/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java +++ b/instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java @@ -10,6 +10,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weaver; import org.glassfish.jersey.message.internal.OutboundJaxrsResponse; @@ -39,7 +40,7 @@ public abstract class ContainerResponse_Instrumentation { public void close() { boolean isLockAcquired = false; try { - isLockAcquired = GenericHelper.acquireLockIfPossible(SERVLET_GET_IS_OPERATION_LOCK); + isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK); if(isLockAcquired) { HttpRequestHelper.postProcessSecurityHook(this.getClass().getName(), getWrappedMessageContext()); } diff --git a/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java b/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java index aa015732b..7990a24c4 100644 --- a/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java +++ b/instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java @@ -10,6 +10,7 @@ import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weaver; import org.glassfish.jersey.message.internal.OutboundJaxrsResponse; @@ -39,7 +40,7 @@ public abstract class ContainerResponse_Instrumentation { public void close() { boolean isLockAcquired = false; try { - isLockAcquired = GenericHelper.acquireLockIfPossible(SERVLET_GET_IS_OPERATION_LOCK); + isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK); if(isLockAcquired) { HttpRequestHelper.postProcessSecurityHook(this.getClass().getName(), getWrappedMessageContext()); } 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 e0528d9e7..4e100890c 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 @@ -178,8 +178,10 @@ public static void preprocessSecurityHook(HttpServletRequest httpServletRequest) public static void postProcessSecurityHook(HttpServletRequest request, HttpServletResponse response, String className, String methodName) { try { - if (!NewRelicSecurity.isHookProcessingActive() - ) { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } + if (!NewRelicSecurity.isHookProcessingActive()) { return; } NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(response.getStatus()); 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 15ebf0561..18bbf3726 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 @@ -177,8 +177,10 @@ public static void preprocessSecurityHook(Request request) { public static void postProcessSecurityHook(Request request, Response response, String className, String methodName) { try { - if (!NewRelicSecurity.isHookProcessingActive() - ) { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } + if (!NewRelicSecurity.isHookProcessingActive()) { return; } NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(response.getStatus()); 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 07b87e142..07a489ddc 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 @@ -179,8 +179,10 @@ public static void preprocessSecurityHook(HttpServletRequest httpServletRequest) public static void postProcessSecurityHook(HttpServletRequest request, HttpServletResponse response, String className, String methodName) { try { - if (!NewRelicSecurity.isHookProcessingActive() - ) { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } + if (!NewRelicSecurity.isHookProcessingActive()) { return; } NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseCode(response.getStatus()); diff --git a/instrumentation-security/ldaptive-1.0/src/main/java/org/ldaptive/AbstractOperation_Instrumentation.java b/instrumentation-security/ldaptive-1.0/src/main/java/org/ldaptive/AbstractOperation_Instrumentation.java index 1d48191a7..3d3eda502 100644 --- a/instrumentation-security/ldaptive-1.0/src/main/java/org/ldaptive/AbstractOperation_Instrumentation.java +++ b/instrumentation-security/ldaptive-1.0/src/main/java/org/ldaptive/AbstractOperation_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.LDAPOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -18,7 +19,7 @@ public abstract class AbstractOperation_Instrumentation protected Response invoke(final Q request) throws LdapException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired && request instanceof SearchRequest) { SearchRequest searchRequest = (SearchRequest) request; @@ -78,10 +79,7 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { - try { - return GenericHelper.acquireLockIfPossible(LDAPUtils.NR_SEC_CUSTOM_ATTRIB_NAME); - } catch (Throwable ignored) {} - return false; + private boolean acquireLockIfPossible(VulnerabilityCaseType ldap) { + return GenericHelper.acquireLockIfPossible(ldap, LDAPUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } } diff --git a/instrumentation-security/ldaptive-2.0/src/main/java/org/ldaptive/AbstractOperation_Instrumentation.java b/instrumentation-security/ldaptive-2.0/src/main/java/org/ldaptive/AbstractOperation_Instrumentation.java index 67f1b09c6..76a624163 100644 --- a/instrumentation-security/ldaptive-2.0/src/main/java/org/ldaptive/AbstractOperation_Instrumentation.java +++ b/instrumentation-security/ldaptive-2.0/src/main/java/org/ldaptive/AbstractOperation_Instrumentation.java @@ -3,6 +3,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.LDAPOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -17,7 +18,7 @@ public abstract class AbstractOperation_Instrumentation { @SuppressWarnings("unchecked") @Trace public AsyncCommand dispatch(RedisCommand_Instrumentation cmd) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(cmd, LettuceUtils.METHOD_DISPATCH); @@ -95,9 +96,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType cachingDataStore) { try { - return GenericHelper.acquireLockIfPossible(LettuceUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(cachingDataStore, LettuceUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/lettuce-5.0/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands_Instrumentation.java b/instrumentation-security/lettuce-5.0/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands_Instrumentation.java index 8a3d141fb..dd0c585f3 100644 --- a/instrumentation-security/lettuce-5.0/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands_Instrumentation.java +++ b/instrumentation-security/lettuce-5.0/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands_Instrumentation.java @@ -11,6 +11,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.RedisOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -33,7 +34,7 @@ public abstract class AbstractRedisAsyncCommands_Instrumentation { @SuppressWarnings("unchecked") @Trace public AsyncCommand dispatch(RedisCommand_Instrumentation cmd) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(cmd, LettuceUtils.METHOD_DISPATCH); @@ -98,9 +99,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType cachingDataStore) { try { - return GenericHelper.acquireLockIfPossible(LettuceUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(cachingDataStore, LettuceUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/low-priority-instrumentation/src/main/java/com/newrelic/agent/security/instrumentation/random/java/util/Random_Instrumentation.java b/instrumentation-security/low-priority-instrumentation/src/main/java/com/newrelic/agent/security/instrumentation/random/java/util/Random_Instrumentation.java index ee490d7ae..edf826045 100644 --- a/instrumentation-security/low-priority-instrumentation/src/main/java/com/newrelic/agent/security/instrumentation/random/java/util/Random_Instrumentation.java +++ b/instrumentation-security/low-priority-instrumentation/src/main/java/com/newrelic/agent/security/instrumentation/random/java/util/Random_Instrumentation.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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.RandomOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -22,7 +23,7 @@ public class Random_Instrumentation { public int nextInt() { - boolean isLockAcquired = acquireLockIfPossible(hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.RANDOM, hashCode()); AbstractOperation operation = null; boolean isOwaspHookEnabled = NewRelicSecurity.getAgent().isLowPriorityInstrumentationEnabled(); if (isOwaspHookEnabled && LowSeverityHelper.isOwaspHookProcessingNeeded()){ @@ -44,7 +45,7 @@ public int nextInt() { } public int nextInt(int bound) { - boolean isLockAcquired = acquireLockIfPossible(hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.RANDOM, hashCode()); AbstractOperation operation = null; boolean isOwaspHookEnabled = NewRelicSecurity.getAgent().isLowPriorityInstrumentationEnabled(); if (isOwaspHookEnabled && LowSeverityHelper.isOwaspHookProcessingNeeded()){ @@ -66,7 +67,7 @@ public int nextInt(int bound) { } public void nextBytes(byte[] bytes) { - boolean isLockAcquired = acquireLockIfPossible(hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.RANDOM, hashCode()); AbstractOperation operation = null; boolean isOwaspHookEnabled = NewRelicSecurity.getAgent().isLowPriorityInstrumentationEnabled(); if (isOwaspHookEnabled && LowSeverityHelper.isOwaspHookProcessingNeeded()){ @@ -86,7 +87,7 @@ public void nextBytes(byte[] bytes) { } public long nextLong() { - boolean isLockAcquired = acquireLockIfPossible(hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.RANDOM, hashCode()); AbstractOperation operation = null; boolean isOwaspHookEnabled = NewRelicSecurity.getAgent().isLowPriorityInstrumentationEnabled(); if (isOwaspHookEnabled && LowSeverityHelper.isOwaspHookProcessingNeeded()){ @@ -108,7 +109,7 @@ public long nextLong() { } public float nextFloat() { - boolean isLockAcquired = acquireLockIfPossible(hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.RANDOM, hashCode()); AbstractOperation operation = null; boolean isOwaspHookEnabled = NewRelicSecurity.getAgent().isLowPriorityInstrumentationEnabled(); if (isOwaspHookEnabled && LowSeverityHelper.isOwaspHookProcessingNeeded()){ @@ -130,7 +131,7 @@ public float nextFloat() { } public double nextDouble() { - boolean isLockAcquired = acquireLockIfPossible(hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.RANDOM, hashCode()); AbstractOperation operation = null; boolean isOwaspHookEnabled = NewRelicSecurity.getAgent().isLowPriorityInstrumentationEnabled(); if (isOwaspHookEnabled && LowSeverityHelper.isOwaspHookProcessingNeeded()){ @@ -152,7 +153,7 @@ public double nextDouble() { } public double nextGaussian() { - boolean isLockAcquired = acquireLockIfPossible(hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.RANDOM, hashCode()); AbstractOperation operation = null; boolean isOwaspHookEnabled = NewRelicSecurity.getAgent().isLowPriorityInstrumentationEnabled(); if (isOwaspHookEnabled && LowSeverityHelper.isOwaspHookProcessingNeeded()){ @@ -174,7 +175,7 @@ public double nextGaussian() { } public boolean nextBoolean() { - boolean isLockAcquired = acquireLockIfPossible(hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.RANDOM, hashCode()); AbstractOperation operation = null; boolean isOwaspHookEnabled = NewRelicSecurity.getAgent().isLowPriorityInstrumentationEnabled(); if (isOwaspHookEnabled && LowSeverityHelper.isOwaspHookProcessingNeeded()){ @@ -246,9 +247,9 @@ private void releaseLock(int hashCode) { } } - private boolean acquireLockIfPossible(int hashCode) { + private boolean acquireLockIfPossible(VulnerabilityCaseType random, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(RandomUtils.NR_SEC_RANDOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(random, RandomUtils.NR_SEC_RANDOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java b/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java index dad1e220d..b7621d8ee 100644 --- a/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java +++ b/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java @@ -4,6 +4,7 @@ import com.mongodb.binding.AsyncReadBinding; import com.mongodb.binding.ReadBinding; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -17,7 +18,7 @@ public class CommandReadOperation_Instrumentation { public T execute(final ReadBinding binding) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_READ, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -35,7 +36,7 @@ public T execute(final ReadBinding binding) { public void executeAsync(final AsyncReadBinding binding, final SingleResultCallback callback) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_READ, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } diff --git a/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java b/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java index 2c89cab27..1755a4fab 100644 --- a/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java +++ b/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java @@ -4,6 +4,7 @@ import com.mongodb.binding.AsyncWriteBinding; import com.mongodb.binding.WriteBinding; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -17,7 +18,7 @@ public class CommandWriteOperation_Instrumentation { public T execute(final WriteBinding binding) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_WRITE, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -35,7 +36,7 @@ public T execute(final WriteBinding binding) { public void executeAsync(final AsyncWriteBinding binding, final SingleResultCallback callback) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_WRITE, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } diff --git a/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/OperationExecutor_Instrumentation.java b/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/OperationExecutor_Instrumentation.java index eca14e3dd..9d61a25b1 100644 --- a/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/OperationExecutor_Instrumentation.java +++ b/instrumentation-security/mongodb-3.0/src/main/java/com/mongodb/operation/OperationExecutor_Instrumentation.java @@ -4,6 +4,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -33,9 +34,9 @@ private void releaseLock(int hashCode) { } } - private boolean acquireLockIfPossible(int hashCode) { + private boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; @@ -44,7 +45,7 @@ private boolean acquireLockIfPossible(int hashCode) { public T execute(ReadOperation operation, ReadPreference readPreference) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getReadAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -62,7 +63,7 @@ public T execute(ReadOperation operation, ReadPreference readPreference) public T execute(WriteOperation operation) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getWriteAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } 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 eb6a3fe42..2c91aba67 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 @@ -15,6 +15,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.NoSQLOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -110,9 +111,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/OperationExecutor_Instrumentation.java b/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/OperationExecutor_Instrumentation.java index 0f5c11214..a33cbe032 100644 --- a/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/OperationExecutor_Instrumentation.java +++ b/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/OperationExecutor_Instrumentation.java @@ -6,6 +6,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -35,9 +36,9 @@ private void releaseLock(int hashCode) { } } - private boolean acquireLockIfPossible(int hashCode) { + private boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; @@ -45,7 +46,7 @@ private boolean acquireLockIfPossible(int hashCode) { public T execute(ReadOperation operation, ReadPreference readPreference, ClientSession session) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getReadAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -63,7 +64,7 @@ public T execute(ReadOperation operation, ReadPreference readPreference, public T execute(ReadOperation operation, ReadPreference readPreference) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getReadAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -82,7 +83,7 @@ public T execute(ReadOperation operation, ReadPreference readPreference) public T execute(WriteOperation operation) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getWriteAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -101,7 +102,7 @@ public T execute(WriteOperation operation) { public T execute(WriteOperation operation, ClientSession session) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getWriteAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } diff --git a/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java b/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java index dad1e220d..b7621d8ee 100644 --- a/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java +++ b/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java @@ -4,6 +4,7 @@ import com.mongodb.binding.AsyncReadBinding; import com.mongodb.binding.ReadBinding; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -17,7 +18,7 @@ public class CommandReadOperation_Instrumentation { public T execute(final ReadBinding binding) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_READ, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -35,7 +36,7 @@ public T execute(final ReadBinding binding) { public void executeAsync(final AsyncReadBinding binding, final SingleResultCallback callback) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_READ, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } diff --git a/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java b/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java index 5de24d163..be2f081e0 100644 --- a/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java +++ b/instrumentation-security/mongodb-3.6/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java @@ -4,6 +4,7 @@ import com.mongodb.binding.AsyncWriteBinding; import com.mongodb.binding.WriteBinding; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -17,7 +18,7 @@ public class CommandWriteOperation_Instrumentation { public T execute(final WriteBinding binding) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_WRITE, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -35,7 +36,7 @@ public T execute(final WriteBinding binding) { public void executeAsync(final AsyncWriteBinding binding, final SingleResultCallback callback) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_WRITE, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } 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 24894c897..b2f7c3f69 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 @@ -15,6 +15,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.NoSQLOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -122,9 +123,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/client/internal/OperationExecutor_Instrumentation.java b/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/client/internal/OperationExecutor_Instrumentation.java index a97325997..31b2762a0 100644 --- a/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/client/internal/OperationExecutor_Instrumentation.java +++ b/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/client/internal/OperationExecutor_Instrumentation.java @@ -8,6 +8,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -37,9 +38,9 @@ private void releaseLock(int hashCode) { } } - private boolean acquireLockIfPossible(int hashCode) { + private boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; @@ -47,7 +48,7 @@ private boolean acquireLockIfPossible(int hashCode) { public T execute(ReadOperation operation, ReadPreference readPreference, @Nullable ClientSession session) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getReadAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -65,7 +66,7 @@ public T execute(ReadOperation operation, ReadPreference readPreference, public T execute(ReadOperation operation, ReadPreference readPreference) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getReadAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -84,7 +85,7 @@ public T execute(ReadOperation operation, ReadPreference readPreference) public T execute(WriteOperation operation) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getWriteAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -103,7 +104,7 @@ public T execute(WriteOperation operation) { public T execute(WriteOperation operation, @Nullable ClientSession session) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getWriteAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } diff --git a/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java b/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java index dad1e220d..b7621d8ee 100644 --- a/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java +++ b/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java @@ -4,6 +4,7 @@ import com.mongodb.binding.AsyncReadBinding; import com.mongodb.binding.ReadBinding; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -17,7 +18,7 @@ public class CommandReadOperation_Instrumentation { public T execute(final ReadBinding binding) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_READ, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -35,7 +36,7 @@ public T execute(final ReadBinding binding) { public void executeAsync(final AsyncReadBinding binding, final SingleResultCallback callback) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_READ, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } diff --git a/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java b/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java index 2c89cab27..1755a4fab 100644 --- a/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java +++ b/instrumentation-security/mongodb-3.7/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java @@ -4,6 +4,7 @@ import com.mongodb.binding.AsyncWriteBinding; import com.mongodb.binding.WriteBinding; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -17,7 +18,7 @@ public class CommandWriteOperation_Instrumentation { public T execute(final WriteBinding binding) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_WRITE, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -35,7 +36,7 @@ public T execute(final WriteBinding binding) { public void executeAsync(final AsyncWriteBinding binding, final SingleResultCallback callback) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_WRITE, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } 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 672fb2804..4a921da83 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 @@ -15,6 +15,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.NoSQLOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -120,9 +121,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/client/internal/OperationExecutor_Instrumentation.java b/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/client/internal/OperationExecutor_Instrumentation.java index e36c58706..4e89a0475 100644 --- a/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/client/internal/OperationExecutor_Instrumentation.java +++ b/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/client/internal/OperationExecutor_Instrumentation.java @@ -9,6 +9,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -38,9 +39,9 @@ private void releaseLock(int hashCode) { } } - private boolean acquireLockIfPossible(int hashCode) { + private boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; @@ -48,7 +49,7 @@ private boolean acquireLockIfPossible(int hashCode) { public T execute(ReadOperation operation, ReadPreference readPreference, ReadConcern readConcern, @Nullable com.mongodb.client.ClientSession session) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getReadAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -66,7 +67,7 @@ public T execute(ReadOperation operation, ReadPreference readPreference, public T execute(ReadOperation operation, ReadPreference readPreference, ReadConcern readConcern) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.getReadAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -85,7 +86,7 @@ public T execute(ReadOperation operation, ReadPreference readPreference, public T execute(WriteOperation operation, ReadConcern readConcern) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); try { if (isLockAcquired) { noSQLOperation = MongoUtil.getWriteAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); @@ -109,7 +110,7 @@ public T execute(WriteOperation operation, ReadConcern readConcern) { public T execute(WriteOperation operation, ReadConcern readConcern, @Nullable ClientSession session) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = acquireLockIfPossible(operation.hashCode()); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, operation.hashCode()); try { if (isLockAcquired) { noSQLOperation = MongoUtil.getWriteAbstractOperation(operation, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); diff --git a/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java b/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java index dad1e220d..b7621d8ee 100644 --- a/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java +++ b/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/operation/CommandReadOperation_Instrumentation.java @@ -4,6 +4,7 @@ import com.mongodb.binding.AsyncReadBinding; import com.mongodb.binding.ReadBinding; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -17,7 +18,7 @@ public class CommandReadOperation_Instrumentation { public T execute(final ReadBinding binding) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_READ, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -35,7 +36,7 @@ public T execute(final ReadBinding binding) { public void executeAsync(final AsyncReadBinding binding, final SingleResultCallback callback) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_READ, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } diff --git a/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java b/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java index 2c89cab27..1755a4fab 100644 --- a/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java +++ b/instrumentation-security/mongodb-3.8/src/main/java/com/mongodb/operation/CommandWriteOperation_Instrumentation.java @@ -4,6 +4,7 @@ import com.mongodb.binding.AsyncWriteBinding; import com.mongodb.binding.WriteBinding; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -17,7 +18,7 @@ public class CommandWriteOperation_Instrumentation { public T execute(final WriteBinding binding) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_WRITE, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } @@ -35,7 +36,7 @@ public T execute(final WriteBinding binding) { public void executeAsync(final AsyncWriteBinding binding, final SingleResultCallback callback) { AbstractOperation noSQLOperation = null; - boolean isLockAcquired = MongoUtil.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = MongoUtil.acquireLockIfPossible(VulnerabilityCaseType.NOSQL_DB_COMMAND, this.hashCode()); if (isLockAcquired) { noSQLOperation = MongoUtil.recordMongoOperation(command, MongoUtil.OP_WRITE, this.getClass().getName(), MongoUtil.METHOD_EXECUTE); } 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 255c9612f..f55664b8b 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 @@ -15,6 +15,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.NoSQLOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -108,9 +109,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType nosqlDbCommand, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(nosqlDbCommand, MongoUtil.NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java index ca9faf1b5..069d85f3e 100644 --- a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java +++ b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java @@ -87,8 +87,11 @@ private static void preprocessSecurityHook(HttpRequestContext requestContext) { private static void postProcessSecurityHook() { try { - if (!NewRelicSecurity.isHookProcessingActive() - ) { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } + + if (!NewRelicSecurity.isHookProcessingActive()) { return; } ServletHelper.executeBeforeExitingTransaction(); diff --git a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java index 3ebd77e15..f59a7efc4 100644 --- a/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java +++ b/instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java @@ -81,8 +81,10 @@ private void preprocessSecurityHook(HttpRequestContext requestContext) { private void postProcessSecurityHook() { try { - if (!NewRelicSecurity.isHookProcessingActive() - ) { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } + if (!NewRelicSecurity.isHookProcessingActive()) { return; } ServletHelper.executeBeforeExitingTransaction(); diff --git a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java index 521808b1a..df4b18d05 100644 --- a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java +++ b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/HttpRequestToMuleEvent_Instrumentation.java @@ -87,8 +87,10 @@ private static void preprocessSecurityHook(HttpRequestContext requestContext) { private static void postProcessSecurityHook() { try { - if (!NewRelicSecurity.isHookProcessingActive() - ) { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } + if (!NewRelicSecurity.isHookProcessingActive()) { return; } ServletHelper.executeBeforeExitingTransaction(); diff --git a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java index 0d1c0d15f..cda5cf549 100644 --- a/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java +++ b/instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/listener/async/RequestHandler_Instrumentation.java @@ -81,8 +81,10 @@ private void preprocessSecurityHook(HttpRequestContext requestContext) { private void postProcessSecurityHook() { try { - if (!NewRelicSecurity.isHookProcessingActive() - ) { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } + if (!NewRelicSecurity.isHookProcessingActive()) { return; } ServletHelper.executeBeforeExitingTransaction(); diff --git a/instrumentation-security/nashorn-jsinjection/src/main/java/jdk/nashorn/api/scripting/NashornScriptEngine_Instrumentation.java b/instrumentation-security/nashorn-jsinjection/src/main/java/jdk/nashorn/api/scripting/NashornScriptEngine_Instrumentation.java index 1236a647f..25b8007db 100644 --- a/instrumentation-security/nashorn-jsinjection/src/main/java/jdk/nashorn/api/scripting/NashornScriptEngine_Instrumentation.java +++ b/instrumentation-security/nashorn-jsinjection/src/main/java/jdk/nashorn/api/scripting/NashornScriptEngine_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.JSInjectionOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -22,7 +23,7 @@ public class NashornScriptEngine_Instrumentation { private Object evalImpl(ScriptFunction_Instrumentation script, ScriptContext ctxt, Global ctxtGlobal) throws ScriptException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.JAVASCRIPT_INJECTION); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(script, JSEngineUtils.METHOD_EVAL_IMPL); @@ -41,7 +42,7 @@ private Object evalImpl(ScriptFunction_Instrumentation script, ScriptContext ctx } private Object evalImpl(final Source src, final ScriptContext ctxt) throws ScriptException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.JAVASCRIPT_INJECTION); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(String.valueOf(src.getContent()), JSEngineUtils.METHOD_EVAL_IMPL); @@ -127,9 +128,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType javascriptInjection) { try { - return GenericHelper.acquireLockIfPossible(JSEngineUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(javascriptInjection, JSEngineUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } 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 10c000dc3..8ef69f185 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 @@ -9,6 +9,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -23,7 +24,7 @@ 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); + isLockAcquired = NettyUtils.acquireNettyLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK); } if (isLockAcquired) { NettyUtils.processSecurityRequest(ctx, msg, getClass().getName()); 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 6a93460f1..3a6bfd8d4 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 @@ -7,6 +7,7 @@ package security.io.netty400.channel; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -23,7 +24,7 @@ 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); + isLockAcquired = NettyUtils.acquireNettyLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND); } if (isLockAcquired) { NettyUtils.processSecurityResponse(ctx, msg); 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 ecdcc8fea..81c468ccc 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 @@ -8,6 +8,7 @@ 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.VulnerabilityCaseType; 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; @@ -229,22 +230,11 @@ public static boolean isNettyLockAcquired(String operationLock) { 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 boolean acquireNettyLockIfPossible(VulnerabilityCaseType reflectedXss, String operationLock) { + return GenericHelper.acquireLockIfPossible(reflectedXss, operationLock+ Thread.currentThread().getId()); } public static void releaseNettyLock(String operationLock) { - try { - if(NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(operationLock + Thread.currentThread().getId(), null); - } - } catch (Throwable ignored){} + GenericHelper.releaseLock(operationLock + Thread.currentThread().getId()); } } 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 index 10c000dc3..8ef69f185 100644 --- 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 @@ -9,6 +9,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.StringUtils; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -23,7 +24,7 @@ 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); + isLockAcquired = NettyUtils.acquireNettyLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK); } if (isLockAcquired) { NettyUtils.processSecurityRequest(ctx, msg, getClass().getName()); 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 index 6a93460f1..3a6bfd8d4 100644 --- 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 @@ -7,6 +7,7 @@ package security.io.netty400.channel; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -23,7 +24,7 @@ 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); + isLockAcquired = NettyUtils.acquireNettyLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, NettyUtils.NR_SEC_NETTY_OPERATIONAL_LOCK_OUTBOUND); } if (isLockAcquired) { NettyUtils.processSecurityResponse(ctx, msg); 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 ecdcc8fea..7901d121d 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 @@ -8,6 +8,7 @@ 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.VulnerabilityCaseType; 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; @@ -229,22 +230,11 @@ public static boolean isNettyLockAcquired(String operationLock) { 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 boolean acquireNettyLockIfPossible(VulnerabilityCaseType reflectedXss, String operationLock) { + return GenericHelper.acquireLockIfPossible(reflectedXss, operationLock + Thread.currentThread().getId()); } public static void releaseNettyLock(String operationLock) { - try { - if(NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(operationLock + Thread.currentThread().getId(), null); - } - } catch (Throwable ignored){} + GenericHelper.releaseLock(operationLock + Thread.currentThread().getId()); } } 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 8711a0146..8234aaa1b 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 @@ -6,15 +6,13 @@ 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.VulnerabilityCaseType; 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.ning.http.client.Request; -import java.net.URI; -import java.net.URISyntaxException; - public class NingHelper { public static final String METHOD_NAME_EXECUTE = "execute"; public static final String NR_SEC_CUSTOM_ATTRIB_NAME = "SSRF_OPERATION_LOCK_NING-"; @@ -81,9 +79,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(httpRequest, NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/ning-async-http-client-1.0.0/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java b/instrumentation-security/ning-async-http-client-1.0.0/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java index b8cd37149..7bb94be73 100644 --- a/instrumentation-security/ning-async-http-client-1.0.0/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java +++ b/instrumentation-security/ning-async-http-client-1.0.0/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java @@ -6,6 +6,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -20,7 +21,7 @@ public class AsyncHttpProvider_Instrumentation { public Future execute(Request request, AsyncHandler handler) throws IOException { - boolean isLockAcquired = NingHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = NingHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST, this.hashCode()); AbstractOperation operation = null; URI uri = null; Future returnObj = null; 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 c2d17e323..16bdab028 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 @@ -6,6 +6,7 @@ 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.VulnerabilityCaseType; 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; @@ -73,9 +74,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(httpRequest, NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/ning-async-http-client-1.1.0/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java b/instrumentation-security/ning-async-http-client-1.1.0/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java index 04511aa11..4e0957511 100644 --- a/instrumentation-security/ning-async-http-client-1.1.0/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java +++ b/instrumentation-security/ning-async-http-client-1.1.0/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java @@ -2,6 +2,7 @@ import com.newrelic.agent.security.instrumentation.ning.http_1_1.NingHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -15,7 +16,7 @@ public class AsyncHttpProvider_Instrumentation { public Future execute(Request request, AsyncHandler handler) throws IOException { - boolean isLockAcquired = NingHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = NingHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST, this.hashCode()); AbstractOperation operation = null; URI uri = null; Future returnObj = null; 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 c4ecbb2f2..b6db3e353 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 @@ -6,6 +6,7 @@ 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.VulnerabilityCaseType; 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; @@ -78,9 +79,9 @@ public static void releaseLock(int hashCode) { } } - public static boolean acquireLockIfPossible(int hashCode) { + public static boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest, int hashCode) { try { - return GenericHelper.acquireLockIfPossible(NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); + return GenericHelper.acquireLockIfPossible(httpRequest, NR_SEC_CUSTOM_ATTRIB_NAME, hashCode); } catch (Throwable ignored) { } return false; diff --git a/instrumentation-security/ning-async-http-client-1.6.1/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java b/instrumentation-security/ning-async-http-client-1.6.1/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java index 97da6d33c..e464b2e96 100644 --- a/instrumentation-security/ning-async-http-client-1.6.1/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java +++ b/instrumentation-security/ning-async-http-client-1.6.1/src/main/java/com/ning/http/client/AsyncHttpProvider_Instrumentation.java @@ -4,6 +4,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -15,7 +16,7 @@ public class AsyncHttpProvider_Instrumentation { public ListenableFuture execute(Request request, AsyncHandler handler) { - boolean isLockAcquired = NingHelper.acquireLockIfPossible(this.hashCode()); + boolean isLockAcquired = NingHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST, this.hashCode()); AbstractOperation operation = null; URI uri = null; ListenableFuture returnObj = null; 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 21c25c193..deb8b30f2 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 @@ -27,35 +27,7 @@ public static boolean skipExistsEvent() { return false; } - public static boolean isLockAcquired() { - try { - return NewRelicSecurity.isHookProcessingActive() && - Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(getNrSecCustomAttribName(), Boolean.class)); - } catch (Throwable ignored) {} - return false; - } - - public static boolean acquireLockIfPossible() { - try { - if (NewRelicSecurity.isHookProcessingActive() && - !isLockAcquired()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), true); - return true; - } - } catch (Throwable ignored){} - return false; - } - - public static void releaseLock() { - try { - if (NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), null); - } - } catch (Throwable ignored) { - } - } - - private static String getNrSecCustomAttribName() { + public static String getNrSecCustomAttribName() { return NR_SEC_CUSTOM_ATTRIB_NAME + Thread.currentThread().getId(); } diff --git a/instrumentation-security/okhttp-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp30/RealCall_Instrumentation.java b/instrumentation-security/okhttp-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp30/RealCall_Instrumentation.java index 20ce78e00..942e374c7 100644 --- a/instrumentation-security/okhttp-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp30/RealCall_Instrumentation.java +++ b/instrumentation-security/okhttp-3.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp30/RealCall_Instrumentation.java @@ -10,6 +10,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -23,16 +24,11 @@ abstract class RealCall_Instrumentation { Request originalRequest = Weaver.callOriginal(); private void releaseLock() { - try { - OkhttpHelper.releaseLock(); - } catch (Throwable ignored) {} + GenericHelper.releaseLock(OkhttpHelper.getNrSecCustomAttribName()); } - private boolean acquireLockIfPossible() { - try { - return OkhttpHelper.acquireLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, OkhttpHelper.getNrSecCustomAttribName()); } /** @@ -40,7 +36,7 @@ private boolean acquireLockIfPossible() { * problem in the agent accessing constructor parameters in any non-no-arg constructor. */ public Response execute() { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = OkhttpHelper.preprocessSecurityHook(getUrl(originalRequest), this.getClass().getName(), 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 ea4ee3192..954687e05 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 @@ -27,35 +27,7 @@ public static boolean skipExistsEvent() { return false; } - public static boolean isLockAcquired() { - try { - return NewRelicSecurity.isHookProcessingActive() && - Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(getNrSecCustomAttribName(), Boolean.class)); - } catch (Throwable ignored) {} - return false; - } - - public static boolean acquireLockIfPossible() { - try { - if (NewRelicSecurity.isHookProcessingActive() && - !isLockAcquired()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), true); - return true; - } - } catch (Throwable ignored){} - return false; - } - - public static void releaseLock() { - try { - if (NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), null); - } - } catch (Throwable ignored) { - } - } - - private static String getNrSecCustomAttribName() { + public static String getNrSecCustomAttribName() { return NR_SEC_CUSTOM_ATTRIB_NAME + Thread.currentThread().getId(); } diff --git a/instrumentation-security/okhttp-3.5.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp35/http/HttpCodec_Instrumentation.java b/instrumentation-security/okhttp-3.5.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp35/http/HttpCodec_Instrumentation.java index 4da46eb6b..73e218b5d 100644 --- a/instrumentation-security/okhttp-3.5.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp35/http/HttpCodec_Instrumentation.java +++ b/instrumentation-security/okhttp-3.5.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp35/http/HttpCodec_Instrumentation.java @@ -10,6 +10,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -21,7 +22,7 @@ public abstract class HttpCodec_Instrumentation { public void writeRequestHeaders(Request request) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if (isLockAcquired) { operation = OkhttpHelper.preprocessSecurityHook(getUrl(request), this.getClass().getName(), @@ -42,18 +43,11 @@ public void writeRequestHeaders(Request request) { } private void releaseLock() { - try { - OkhttpHelper.releaseLock(); - } catch (Throwable ignored) { - } + GenericHelper.releaseLock(OkhttpHelper.getNrSecCustomAttribName()); } - private boolean acquireLockIfPossible() { - try { - return OkhttpHelper.acquireLockIfPossible(); - } catch (Throwable ignored) { - } - return false; + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, OkhttpHelper.getNrSecCustomAttribName()); } private String getUrl(Request originalRequest) { diff --git a/instrumentation-security/okhttp-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp40/ExchangeCodec_Instrumentation.java b/instrumentation-security/okhttp-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp40/ExchangeCodec_Instrumentation.java index d63ee8803..4831696db 100644 --- a/instrumentation-security/okhttp-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp40/ExchangeCodec_Instrumentation.java +++ b/instrumentation-security/okhttp-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/okhttp40/ExchangeCodec_Instrumentation.java @@ -10,6 +10,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -22,16 +23,11 @@ public abstract class ExchangeCodec_Instrumentation { private void releaseLock() { - try { - OkhttpHelper.releaseLock(); - } catch (Throwable ignored) {} + GenericHelper.releaseLock(OkhttpHelper.getNrSecCustomAttribName()); } - private boolean acquireLockIfPossible() { - try { - return OkhttpHelper.acquireLockIfPossible(); - } catch (Throwable ignored) {} - return false; + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, OkhttpHelper.getNrSecCustomAttribName()); } private String getUrl(Request originalRequest) { @@ -46,7 +42,7 @@ private String getUrl(Request originalRequest) { } public void writeRequestHeaders(Request request) throws IOException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = OkhttpHelper.preprocessSecurityHook(getUrl(request), this.getClass().getName(), OkhttpHelper.METHOD_EXECUTE); 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 7f2d936da..2274e5ef7 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 @@ -27,35 +27,7 @@ public static boolean skipExistsEvent() { return false; } - public static boolean isLockAcquired() { - try { - return NewRelicSecurity.isHookProcessingActive() && - Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(getNrSecCustomAttribName(), Boolean.class)); - } catch (Throwable ignored) {} - return false; - } - - public static boolean acquireLockIfPossible() { - try { - if (NewRelicSecurity.isHookProcessingActive() && - !isLockAcquired()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), true); - return true; - } - } catch (Throwable ignored){} - return false; - } - - public static void releaseLock() { - try { - if (NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), null); - } - } catch (Throwable ignored) { - } - } - - private static String getNrSecCustomAttribName() { + public static String getNrSecCustomAttribName() { return NR_SEC_CUSTOM_ATTRIB_NAME + Thread.currentThread().getId(); } diff --git a/instrumentation-security/r2dbc-generic/src/main/java/io/r2dbc/spi/Batch_Instrumentation.java b/instrumentation-security/r2dbc-generic/src/main/java/io/r2dbc/spi/Batch_Instrumentation.java index f8fccbf2d..859b689f0 100644 --- a/instrumentation-security/r2dbc-generic/src/main/java/io/r2dbc/spi/Batch_Instrumentation.java +++ b/instrumentation-security/r2dbc-generic/src/main/java/io/r2dbc/spi/Batch_Instrumentation.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.R2dbcHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.NewField; import com.newrelic.api.agent.weaver.Weave; @@ -19,7 +20,7 @@ public Batch add(String s){ } public Publisher execute() { - boolean isLockAcquired = R2dbcHelper.acquireLockIfPossible(); + boolean isLockAcquired = R2dbcHelper.acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if (isLockAcquired) { operation = R2dbcHelper.preprocessSecurityHook(sql, R2dbcHelper.METHOD_EXECUTE, this.getClass().getName(), null, false); diff --git a/instrumentation-security/r2dbc-generic/src/main/java/io/r2dbc/spi/Statement_Instrumention.java b/instrumentation-security/r2dbc-generic/src/main/java/io/r2dbc/spi/Statement_Instrumention.java index 9ca41985b..34934c952 100644 --- a/instrumentation-security/r2dbc-generic/src/main/java/io/r2dbc/spi/Statement_Instrumention.java +++ b/instrumentation-security/r2dbc-generic/src/main/java/io/r2dbc/spi/Statement_Instrumention.java @@ -2,6 +2,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.R2dbcHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.NewField; import com.newrelic.api.agent.weaver.Weave; @@ -25,7 +26,7 @@ public class Statement_Instrumention { private boolean lock = false; public Publisher execute() { - boolean isLockAcquired = R2dbcHelper.acquireLockIfPossible(); + boolean isLockAcquired = R2dbcHelper.acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if (isLockAcquired) { operation = R2dbcHelper.preprocessSecurityHook(sql, R2dbcHelper.METHOD_EXECUTE, this.getClass().getName(), params, isPrepared); diff --git a/instrumentation-security/r2dbc-h2/src/main/java/io/r2dbc/h2/client/Client_Instrumentation.java b/instrumentation-security/r2dbc-h2/src/main/java/io/r2dbc/h2/client/Client_Instrumentation.java index ccada5043..99d5ea4db 100644 --- a/instrumentation-security/r2dbc-h2/src/main/java/io/r2dbc/h2/client/Client_Instrumentation.java +++ b/instrumentation-security/r2dbc-h2/src/main/java/io/r2dbc/h2/client/Client_Instrumentation.java @@ -5,6 +5,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.R2dbcHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; import com.newrelic.api.agent.security.schema.R2DBCVendor; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SQLOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -18,7 +19,7 @@ public class Client_Instrumentation { public void execute(String sql) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = R2dbcHelper.acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND); AbstractOperation operation = null; if (isLockAcquired) { operation = preprocessSecurityHook(sql, R2dbcHelper.METHOD_EXECUTE); @@ -81,12 +82,4 @@ private void releaseLock() { } catch (Throwable ignored) { } } - - private boolean acquireLockIfPossible() { - try { - return R2dbcHelper.acquireLockIfPossible(); - } catch (Throwable ignored) { - } - return false; - } } diff --git a/instrumentation-security/rhino-jsinjection/src/main/java/org/mozilla/javascript/ScriptRuntime_Instrumentation.java b/instrumentation-security/rhino-jsinjection/src/main/java/org/mozilla/javascript/ScriptRuntime_Instrumentation.java index eab41aa5d..7a5c2ffbc 100644 --- a/instrumentation-security/rhino-jsinjection/src/main/java/org/mozilla/javascript/ScriptRuntime_Instrumentation.java +++ b/instrumentation-security/rhino-jsinjection/src/main/java/org/mozilla/javascript/ScriptRuntime_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.JSInjectionOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -22,7 +23,7 @@ public static Object doTopCall(Callable callable, Context_Instrumentation cx, Sc AbstractOperation operation = null; if(cx != null) { code = cx.hashCode(); - isLockAcquired = acquireLockIfPossible(code); + isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.JAVASCRIPT_INJECTION, code); if (isLockAcquired) { operation = preprocessSecurityHook(code, JSEngineUtils.METHOD_EXEC, cx); } @@ -81,9 +82,9 @@ private static void releaseLock(int code) { } catch (Throwable ignored) {} } - private static boolean acquireLockIfPossible(int code) { + private static boolean acquireLockIfPossible(VulnerabilityCaseType javascriptInjection, int code) { try { - return GenericHelper.acquireLockIfPossible(JSEngineUtils.NR_SEC_CUSTOM_ATTRIB_NAME+code); + return GenericHelper.acquireLockIfPossible(javascriptInjection, JSEngineUtils.NR_SEC_CUSTOM_ATTRIB_NAME+code); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/saxpath/src/main/java/org/saxpath/XPathReader_Instrumentation.java b/instrumentation-security/saxpath/src/main/java/org/saxpath/XPathReader_Instrumentation.java index 438adef1d..fd01d9a7b 100644 --- a/instrumentation-security/saxpath/src/main/java/org/saxpath/XPathReader_Instrumentation.java +++ b/instrumentation-security/saxpath/src/main/java/org/saxpath/XPathReader_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.XPathOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -17,7 +18,7 @@ public abstract class XPathReader_Instrumentation { public void parse(String xpath) throws SAXPathException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(xpath, XPATHUtils.METHOD_PARSE); @@ -73,9 +74,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType xpath) { try { - return GenericHelper.acquireLockIfPossible(XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(xpath, XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } 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 bf9930a22..1b5a12ea2 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 @@ -93,6 +93,9 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } 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 c62d5a0a7..e4cdc168d 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 @@ -94,6 +94,9 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } 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 e3ab77671..be10a2e4d 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 @@ -99,6 +99,9 @@ private void preprocessSecurityHook(ServletRequest_Instrumentation request, Serv private void postProcessSecurityHook(ServletRequest_Instrumentation request, ServletResponse_Instrumentation response) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } 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 4ffa56d11..1362bbe9c 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 @@ -92,6 +92,9 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } 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 fa7051cb3..e82bf14d1 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 @@ -94,6 +94,9 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } 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 a8b32bfe1..803e80689 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 @@ -98,6 +98,9 @@ private void preprocessSecurityHook(ServletRequest_Instrumentation request, Serv private void postProcessSecurityHook(ServletRequest_Instrumentation request, ServletResponse_Instrumentation response) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } 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 3b2ff79a9..d602a19d9 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 @@ -93,6 +93,9 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } 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 c2855bd94..5edd9af5c 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 @@ -94,6 +94,9 @@ private void preprocessSecurityHook(ServletRequest request, ServletResponse resp private void postProcessSecurityHook(ServletRequest request, ServletResponse response) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } 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 d7ac8309c..3eb80fe5a 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 @@ -98,6 +98,9 @@ private void preprocessSecurityHook(ServletRequest_Instrumentation request, Serv private void postProcessSecurityHook(ServletRequest_Instrumentation request, ServletResponse_Instrumentation response) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } if (!NewRelicSecurity.isHookProcessingActive() || Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute("RXSS_PROCESSED", Boolean.class)) ) { return; 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 ccfccafa1..36717c4e3 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 @@ -3,6 +3,7 @@ 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.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -18,7 +19,7 @@ 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()); + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SprayHttpUtils.getNrSecCustomAttribNameForResponse()); try { if (isLockAcquired && response.entity().nonEmpty()) { NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(new StringBuilder(response.entity().data().asString(StandardCharsets.UTF_8))); 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 41d03a37e..0c23bf39a 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,6 +11,7 @@ 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.schema.VulnerabilityCaseType; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; @@ -25,7 +26,7 @@ public class SprayToResponseMarshallingContext { @Trace(async = true) public void marshalTo(HttpResponse httpResponse) { - boolean isLockAcquired = GenericHelper.acquireLockIfPossible(SprayHttpUtils.getNrSecCustomAttribNameForResponse()); + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SprayHttpUtils.getNrSecCustomAttribNameForResponse()); try { if (isLockAcquired && httpResponse.entity().nonEmpty()) { NewRelicSecurity.getAgent().getSecurityMetaData().getResponse().setResponseBody(new StringBuilder(httpResponse.entity().data().asString(StandardCharsets.UTF_8))); 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 e773eeb16..92675bf0d 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 @@ -10,6 +10,7 @@ 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.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -19,7 +20,7 @@ public class ExchangeFunction_Instrumentation { public Mono exchange(ClientRequest request) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = SpringWebClientHelper.preprocessSecurityHook(request.url(), request.method(), this.getClass().getName(), SpringWebClientHelper.METHOD_EXECHANGE); @@ -45,8 +46,8 @@ private void releaseLock() { } - private boolean acquireLockIfPossible() { - return GenericHelper.acquireLockIfPossible(SpringWebClientHelper.getNrSecCustomAttribName()); + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, SpringWebClientHelper.getNrSecCustomAttribName()); } } diff --git a/instrumentation-security/spymemcached-2.12.0/src/main/java/net/spy/memcached/MemcachedClient_Instrumentation.java b/instrumentation-security/spymemcached-2.12.0/src/main/java/net/spy/memcached/MemcachedClient_Instrumentation.java index 66658d078..107c9db98 100644 --- a/instrumentation-security/spymemcached-2.12.0/src/main/java/net/spy/memcached/MemcachedClient_Instrumentation.java +++ b/instrumentation-security/spymemcached-2.12.0/src/main/java/net/spy/memcached/MemcachedClient_Instrumentation.java @@ -4,6 +4,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.MemcachedOperation; import com.newrelic.api.agent.weaver.Weave; @@ -19,7 +20,7 @@ public class MemcachedClient_Instrumentation { private OperationFuture asyncStore(StoreType storeType, String key, int exp, T value, Transcoder tc) { - boolean isLockAcquired = GenericHelper.acquireLockIfPossible(MemcachedHelper.NR_SEC_CUSTOM_ATTRIB_NAME, value.hashCode()); + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, MemcachedHelper.NR_SEC_CUSTOM_ATTRIB_NAME, value.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = MemcachedHelper.preprocessSecurityHook(storeType.name(), MemcachedHelper.WRITE, key, value, this.getClass().getName(), MemcachedHelper.METHOD_ASYNC_STORE); @@ -38,7 +39,7 @@ private OperationFuture asyncStore(StoreType storeType, private OperationFuture asyncCat(ConcatenationType catType, long cas, String key, T value, Transcoder tc) { - boolean isLockAcquired = GenericHelper.acquireLockIfPossible(MemcachedHelper.NR_SEC_CUSTOM_ATTRIB_NAME, value.hashCode()); + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, MemcachedHelper.NR_SEC_CUSTOM_ATTRIB_NAME, value.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = MemcachedHelper.preprocessSecurityHook(catType.name(), MemcachedHelper.UPDATE, key, value, this.getClass().getName(), MemcachedHelper.METHOD_ASYNC_CAT); @@ -57,7 +58,7 @@ private OperationFuture asyncCat(ConcatenationType catType, public OperationFuture asyncCAS(String key, long casId, int exp, T value, Transcoder tc) { - boolean isLockAcquired = GenericHelper.acquireLockIfPossible(MemcachedHelper.NR_SEC_CUSTOM_ATTRIB_NAME, value.hashCode()); + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.CACHING_DATA_STORE, MemcachedHelper.NR_SEC_CUSTOM_ATTRIB_NAME, value.hashCode()); AbstractOperation operation = null; if (isLockAcquired) { operation = MemcachedHelper.preprocessSecurityHook(StoreType.set.name(), MemcachedHelper.WRITE, key, value, this.getClass().getName(), MemcachedHelper.METHOD_ASYNC_CAS); 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 742298c65..83313fc5a 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 @@ -77,6 +77,9 @@ private void preprocessSecurityHook(HttpExchange exchange) { } private void postProcessSecurityHook(HttpExchange exchange) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } if (!NewRelicSecurity.isHookProcessingActive()) { return; } 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 90c4cdb6d..13ffb8068 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 @@ -77,6 +77,9 @@ private void preprocessSecurityHook(HttpExchange exchange) { } private void postProcessSecurityHook(HttpExchange exchange) { try { + if(NewRelicSecurity.getAgent().getIastDetectionCategory().getRxssEnabled()){ + return; + } if (!NewRelicSecurity.isHookProcessingActive()) { return; } diff --git a/instrumentation-security/unboundid-ldapsdk/src/main/java/com/unboundid/ldap/sdk/LDAPInterface_Instrumentation.java b/instrumentation-security/unboundid-ldapsdk/src/main/java/com/unboundid/ldap/sdk/LDAPInterface_Instrumentation.java index 25132bd44..6ff09631d 100644 --- a/instrumentation-security/unboundid-ldapsdk/src/main/java/com/unboundid/ldap/sdk/LDAPInterface_Instrumentation.java +++ b/instrumentation-security/unboundid-ldapsdk/src/main/java/com/unboundid/ldap/sdk/LDAPInterface_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.LDAPOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -17,7 +18,7 @@ public class LDAPInterface_Instrumentation { public SearchResult search(final SearchRequest searchRequest) throws LDAPSearchException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(searchRequest.getBaseDN(), searchRequest.getFilter().toString(), LDAPUtils.METHOD_SEARCH); @@ -75,9 +76,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType ldap) { try { - return GenericHelper.acquireLockIfPossible(LDAPUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(ldap, LDAPUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } diff --git a/instrumentation-security/vertx-core-3.3.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/VertxClientHelper.java b/instrumentation-security/vertx-core-3.3.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/VertxClientHelper.java index 53b28229c..4436c41fe 100644 --- a/instrumentation-security/vertx-core-3.3.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/VertxClientHelper.java +++ b/instrumentation-security/vertx-core-3.3.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/VertxClientHelper.java @@ -1,6 +1,7 @@ package com.newrelic.agent.security.instrumentation.vertx; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; public class VertxClientHelper { public static final String NR_SEC_CUSTOM_ATTRIB_NAME = "VERTX_CORE_OPERATION_LOCK-"; @@ -14,7 +15,7 @@ public static void releaseLock() { GenericHelper.releaseLock(getNrSecCustomAttribName()); } - public static boolean acquireLockIfPossible() { - return GenericHelper.acquireLockIfPossible(getNrSecCustomAttribName()); + public static boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, getNrSecCustomAttribName()); } } diff --git a/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java b/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java index 2ca52df71..2e3565615 100644 --- a/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java +++ b/instrumentation-security/vertx-core-3.3.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java @@ -6,6 +6,7 @@ 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; import com.newrelic.api.agent.security.utils.SSRFUtils; @@ -23,7 +24,7 @@ public abstract class HttpClientRequestImpl_Instrumentation { private String hostHeader() { return Weaver.callOriginal();} public void end(Buffer chunk) { - boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(); + boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { String uri = getAbsoluteUri(ssl, hostHeader(), uri()); @@ -41,7 +42,7 @@ public void end(Buffer chunk) { } public void end() { - boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(); + boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { String uri = getAbsoluteUri(ssl, hostHeader(), uri()); diff --git a/instrumentation-security/vertx-core-3.4.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/VertxClientHelper.java b/instrumentation-security/vertx-core-3.4.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/VertxClientHelper.java index e6efeac10..689089a31 100644 --- a/instrumentation-security/vertx-core-3.4.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/VertxClientHelper.java +++ b/instrumentation-security/vertx-core-3.4.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/VertxClientHelper.java @@ -1,6 +1,7 @@ package com.newrelic.agent.security.instrumentation.vertx; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; public class VertxClientHelper { public static final String NR_SEC_CUSTOM_ATTRIB_NAME = "VERTX_CORE_OPERATION_LOCK-"; @@ -15,7 +16,7 @@ public static void releaseLock() { GenericHelper.releaseLock(getNrSecCustomAttribName()); } - public static boolean acquireLockIfPossible() { - return GenericHelper.acquireLockIfPossible(getNrSecCustomAttribName()); + public static boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, getNrSecCustomAttribName()); } } diff --git a/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java b/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java index d40dd472c..bc671b229 100644 --- a/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java +++ b/instrumentation-security/vertx-core-3.4.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java @@ -6,6 +6,7 @@ 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; import com.newrelic.api.agent.security.utils.SSRFUtils; @@ -27,7 +28,7 @@ public abstract class HttpClientRequestImpl_Instrumentation { } public void end(Buffer chunk) { - boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(); + boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(absoluteURI(), this.getClass().getName(), VertxClientHelper.METHOD_END); @@ -44,7 +45,7 @@ public void end(Buffer chunk) { } public void end() { - boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(); + boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(absoluteURI(), this.getClass().getName(), VertxClientHelper.METHOD_END); diff --git a/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java b/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java index afdbc3b3c..2b2b75db3 100644 --- a/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java +++ b/instrumentation-security/vertx-core-3.7.1/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java @@ -10,6 +10,7 @@ import com.newrelic.agent.security.instrumentation.vertx.web.VertxClientHelper; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; import com.newrelic.api.agent.security.schema.AbstractOperation; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import io.vertx.core.AsyncResult; @@ -26,7 +27,7 @@ public abstract class HttpClientRequestImpl_Instrumentation { public abstract String absoluteURI(); public void end(Buffer chunk) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = VertxClientHelper.preprocessSecurityHook(absoluteURI(), this.getClass().getName(), @@ -45,7 +46,7 @@ public void end(Buffer chunk) { public void end(Buffer chunk, Handler> handler) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = VertxClientHelper.preprocessSecurityHook(absoluteURI(), this.getClass().getName(), @@ -64,7 +65,7 @@ public void end(Buffer chunk, Handler> handler) { public void end() { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = VertxClientHelper.preprocessSecurityHook(absoluteURI(), this.getClass().getName(), @@ -83,7 +84,7 @@ public void end() { public void end(Handler> handler) { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = VertxClientHelper.preprocessSecurityHook(absoluteURI(), this.getClass().getName(), @@ -103,7 +104,7 @@ private void releaseLock() { GenericHelper.releaseLock(VertxClientHelper.getNrSecCustomAttribName()); } - private boolean acquireLockIfPossible() { - return GenericHelper.acquireLockIfPossible(VertxClientHelper.getNrSecCustomAttribName()); + private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, VertxClientHelper.getNrSecCustomAttribName()); } } diff --git a/instrumentation-security/vertx-core-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/web/VertxClientHelper.java b/instrumentation-security/vertx-core-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/web/VertxClientHelper.java index 69bc6787e..8ead6362e 100644 --- a/instrumentation-security/vertx-core-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/web/VertxClientHelper.java +++ b/instrumentation-security/vertx-core-4.0.0/src/main/java/com/newrelic/agent/security/instrumentation/vertx/web/VertxClientHelper.java @@ -1,6 +1,7 @@ package com.newrelic.agent.security.instrumentation.vertx.web; import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; public class VertxClientHelper { @@ -17,7 +18,7 @@ public static void releaseLock() { GenericHelper.releaseLock(getNrSecCustomAttribName()); } - public static boolean acquireLockIfPossible() { - return GenericHelper.acquireLockIfPossible(getNrSecCustomAttribName()); + public static boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { + return GenericHelper.acquireLockIfPossible(httpRequest, getNrSecCustomAttribName()); } } diff --git a/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java b/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java index 21c3f7f25..8c64cf881 100644 --- a/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java +++ b/instrumentation-security/vertx-core-4.0.0/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl_Instrumentation.java @@ -13,6 +13,7 @@ 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.SSRFOperation; import com.newrelic.api.agent.security.utils.SSRFUtils; @@ -35,7 +36,7 @@ public abstract class HttpClientRequestImpl_Instrumentation { public Future end(Buffer chunk) { Future result; - boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(); + boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(absoluteURI(), this.getClass().getName(), VertxClientHelper.METHOD_END); @@ -53,7 +54,7 @@ public Future end(Buffer chunk) { } public void end(Buffer chunk, Handler> handler) { - boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(); + boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(absoluteURI(), this.getClass().getName(), VertxClientHelper.METHOD_END); @@ -71,7 +72,7 @@ public void end(Buffer chunk, Handler> handler) { public void end(Handler> handler){ - boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(); + boolean isLockAcquired = VertxClientHelper.acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(absoluteURI(), this.getClass().getName(), diff --git a/instrumentation-security/xalan-xpath/src/main/java/org/apache/xpath/XPath_Instrumentation.java b/instrumentation-security/xalan-xpath/src/main/java/org/apache/xpath/XPath_Instrumentation.java index 17dd55fbc..7250b91c6 100644 --- a/instrumentation-security/xalan-xpath/src/main/java/org/apache/xpath/XPath_Instrumentation.java +++ b/instrumentation-security/xalan-xpath/src/main/java/org/apache/xpath/XPath_Instrumentation.java @@ -4,6 +4,7 @@ import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; 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.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.XPathOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -23,7 +24,7 @@ public abstract class XPath_Instrumentation { abstract public String getPatternString(); public XObject execute(XPathContext var1, Node var2, PrefixResolver var3) throws TransformerException { - boolean isLockAcquired = acquireLockIfPossible(); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.XPATH); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(getPatternString(), XPATHUtils.METHOD_EXECUTE); @@ -82,9 +83,9 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible() { + private boolean acquireLockIfPossible(VulnerabilityCaseType xpath) { try { - return GenericHelper.acquireLockIfPossible(XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); + return GenericHelper.acquireLockIfPossible(xpath, XPATHUtils.NR_SEC_CUSTOM_ATTRIB_NAME); } catch (Throwable ignored) {} return false; } From f7240dcadba4d424708e11599c96052b34f42616 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 14 Aug 2024 10:56:25 +0530 Subject: [PATCH 086/122] Update gradle.properties to use 1.2.6 as json version --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 8e99a4eca..9cf70671d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # The agent version. -agentVersion=1.4.0 -jsonVersion=1.2.3 +agentVersion=1.4.1 +jsonVersion=1.2.6 # Updated exposed NR APM API version. nrAPIVersion=8.12.0 From d14387ac867adcbb071c8127fd066ddc9d441c7b Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 14 Aug 2024 13:22:36 +0530 Subject: [PATCH 087/122] Update release date --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 58f975a07..3ec4c627e 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). -## [1.4.1] - TBD +## [1.4.1] - 2024-8-14 ### Adds - [PR-296](https://github.com/newrelic/csec-java-agent/pull/296) Apache Solr Support: The security agent now also supports Apache Solr Version 4.0.0 and above. [NR-288599](https://new-relic.atlassian.net/browse/NR-288599) - [PR-275](https://github.com/newrelic/csec-java-agent/pull/275) The maximum permissible size for a request body for scan will be set at 500KB. [NR-174195](https://new-relic.atlassian.net/browse/NR-174195) From eddc24c79ed38dfc107d1fd2568a9197c1c90c41 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 15 Aug 2024 16:41:32 +0530 Subject: [PATCH 088/122] fix for delay in start fix for event being generated for HTTP request and SYSTEM COMMAND --- .../newrelic/api/agent/security/Agent.java | 9 ++++++--- .../schema/policy/IastDetectionCategory.java | 20 +++++++++---------- 2 files changed, 16 insertions(+), 13 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 3c93eb2df..f06d3fc40 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 @@ -10,6 +10,7 @@ import com.newrelic.agent.security.intcodeagent.constants.AgentServices; import com.newrelic.agent.security.intcodeagent.constants.HttpStatusCodes; import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessor; +import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessorThreadPool; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.filelogging.LogFileHelper; import com.newrelic.agent.security.intcodeagent.models.collectorconfig.AgentMode; @@ -145,7 +146,7 @@ private void triggerNrSecurity() { LogLevel.INFO, "[STEP-3] => Gathering information about the application", this.getClass().getName()); - logger.logInit(LogLevel.INFO, NewRelic.getAgent().getConfig().getValue(LowSeverityHelper.LOW_SEVERITY_HOOKS_ENABLED, LowSeverityHelper.DEFAULT)? + logger.logInit(LogLevel.INFO, !config.getAgentMode().getSkipScan().getIastDetectionCategory().getInsecureSettingsEnabled()? "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()); @@ -256,6 +257,7 @@ public boolean refreshState(java.net.URL agentJarURL, Instrumentation instrument this.instrumentation = instrumentation; if (isInitialised()) { config.setNRSecurityEnabled(false); + AgentInfo.getInstance().setAgentActive(false); cancelActiveServiceTasks(); } initialise(); @@ -266,14 +268,15 @@ public boolean refreshState(java.net.URL agentJarURL, Instrumentation instrument private void cancelActiveServiceTasks() { /** - * Drain the pools (RestClient, EventSend, Dispatcher) before websocket close * Websocket * policy * HealthCheck */ WSClient.shutDownWSClientAbnormal(false); HealthCheckScheduleThread.getInstance().cancelTask(true); + WSReconnectionST.cancelTask(true); FileCleaner.cancelTask(); + ControlCommandProcessorThreadPool.shutDownPool(); } @@ -776,7 +779,7 @@ public Instrumentation getInstrumentation() { @Override public boolean isLowPriorityInstrumentationEnabled() { - return NewRelicSecurity.isHookProcessingActive() && NewRelic.getAgent().getConfig().getValue(LowSeverityHelper.LOW_SEVERITY_HOOKS_ENABLED, LowSeverityHelper.DEFAULT); + return NewRelicSecurity.isHookProcessingActive() && !config.getAgentMode().getSkipScan().getIastDetectionCategory().getInsecureSettingsEnabled(); } public void setApplicationConnectionConfig(int port, String scheme) { diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java index 46933e1b0..c555dda1d 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java @@ -5,16 +5,16 @@ public class IastDetectionCategory { public static final String STR_COMMA = ","; - Boolean sqlInjectionEnabled = true; - Boolean insecureSettingsEnabled = true; - Boolean invalidFileAccessEnabled = true; - Boolean noSqlInjectionEnabled = true; - Boolean rxssEnabled = true; - Boolean commandInjectionEnabled = true; - Boolean ldapInjectionEnabled = true; - Boolean javascriptInjectionEnabled = true; - Boolean xpathInjectionEnabled = true; - Boolean ssrfEnabled = true; + Boolean sqlInjectionEnabled = false; + Boolean insecureSettingsEnabled = false; + Boolean invalidFileAccessEnabled = false; + Boolean noSqlInjectionEnabled = false; + Boolean rxssEnabled = false; + Boolean commandInjectionEnabled = false; + Boolean ldapInjectionEnabled = false; + Boolean javascriptInjectionEnabled = false; + Boolean xpathInjectionEnabled = false; + Boolean ssrfEnabled = false; private String disabledCategoriesCSV; From 16cbfb2a636c46df97dd9b1189800462e202fad8 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 15 Aug 2024 16:44:36 +0530 Subject: [PATCH 089/122] fix for event being generated for HTTP request and SYSTEM COMMAND --- .../lang/ProcessImpl_Instrumentation.java | 15 ++++- .../javax/naming/Context_Instrumentation.java | 16 ++--- .../instrumentation/urlconnection/Helper.java | 1 + .../URLConnection_Instrumentation.java | 64 +++++++++++-------- 4 files changed, 59 insertions(+), 37 deletions(-) diff --git a/instrumentation-security/java-lang/src/main/java/java/lang/ProcessImpl_Instrumentation.java b/instrumentation-security/java-lang/src/main/java/java/lang/ProcessImpl_Instrumentation.java index c8d193236..57029faad 100644 --- a/instrumentation-security/java-lang/src/main/java/java/lang/ProcessImpl_Instrumentation.java +++ b/instrumentation-security/java-lang/src/main/java/java/lang/ProcessImpl_Instrumentation.java @@ -3,6 +3,7 @@ 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.VulnerabilityCaseType; import com.newrelic.api.agent.security.schema.exceptions.NewRelicSecurityException; import com.newrelic.api.agent.security.schema.operation.ForkExecOperation; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -22,8 +23,18 @@ static Process start(String[] cmdarray, ProcessBuilder.Redirect[] redirects, boolean redirectErrorStream) throws IOException { Process p = null; - AbstractOperation operation = preprocessSecurityHook(cmdarray, environment); - p = Weaver.callOriginal(); + boolean isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.SYSTEM_COMMAND, "SYSTEM_COMMAND_"); + AbstractOperation operation = null; + if(isLockAcquired) { + operation = preprocessSecurityHook(cmdarray, environment); + } + try { + p = Weaver.callOriginal(); + } finally { + if(isLockAcquired){ + GenericHelper.releaseLock("SYSTEM_COMMAND_"); + } + } registerExitOperation(operation); return p; } 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 ded02cd36..63c9611c3 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 @@ -19,7 +19,7 @@ public abstract class Context_Instrumentation { public Object lookup(Name name) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); List operations = null; if(isLockAcquired) { operations = preprocessSecurityHook(name.getAll(), JNDIUtils.METHOD_LOOKUP); @@ -37,7 +37,7 @@ public Object lookup(Name name) throws NamingException { } public Object lookupLink(Name name) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); List operations = null; if(isLockAcquired) { operations = preprocessSecurityHook(name.getAll(), JNDIUtils.METHOD_LOOKUP); @@ -55,7 +55,7 @@ public Object lookupLink(Name name) throws NamingException { } public Object lookup(String name) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(name, JNDIUtils.METHOD_LOOKUP); @@ -73,7 +73,7 @@ public Object lookup(String name) throws NamingException { } public Object lookupLink(String name) throws NamingException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.LDAP); + boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(name, JNDIUtils.METHOD_LOOKUP); @@ -100,8 +100,8 @@ private void registerExitOperation(boolean isLockAcquired, List Date: Thu, 15 Aug 2024 16:53:06 +0530 Subject: [PATCH 090/122] fix shutting of agent after a certain duration --- .../intcodeagent/controlcommand/ControlCommandProcessor.java | 2 +- .../src/main/java/com/newrelic/api/agent/security/Agent.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java index e280ccc2e..7bfdaa16f 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java @@ -69,7 +69,7 @@ public class ControlCommandProcessor implements Runnable { private long receiveTimestamp; - private static Instant iastReplayRequestMsgReceiveTime; + private static Instant iastReplayRequestMsgReceiveTime = Instant.now(); private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); 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 f06d3fc40..fd09dd7d5 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 @@ -182,7 +182,7 @@ private void IastShutdown() { if(ControlCommandProcessor.getIastReplayRequestMsgReceiveTime().isBefore(Instant.now().minus(5, ChronoUnit.MINUTES))){ logger.log(LogLevel.WARNING, "IAST scan is still in progress, may have undetected vulnerabilities. Please increase scan duration and restart application.", Agent.class.getName()); } - logger.log(LogLevel.FINER, "Scan duration completed, IAST Scan shutting down.", Agent.class.getName()); + logger.log(LogLevel.INFO, "Scan duration completed, IAST Scan shutting down.", Agent.class.getName()); InstrumentationUtils.shutdownLogic(); } From 9d2f10f4c591efa8d5189e8e0bd1677193459d1b Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 15 Aug 2024 17:15:28 +0530 Subject: [PATCH 091/122] Disable agent on incorrect config --- .../newrelic/agent/security/AgentConfig.java | 72 ++++++++++--------- .../newrelic/api/agent/security/Agent.java | 21 +++--- 2 files changed, 53 insertions(+), 40 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 083ebed70..d69bd5fbe 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 @@ -134,50 +134,58 @@ private void instantiateAgentMode(String groupName) { try { readScanSchedule(); + readSkipScan(); } catch (RestrictionModeException e){ - System.err.println("[NR-CSEC-JA] Error while reading Scan Schedule Configuration. Security will be disabled."); - NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading Scan Schedule Configuration. Security will be disabled."); + System.err.println("[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled."); + NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled. Message :{}", e.getMessage()); NewRelic.noticeError(e, Agent.getCustomNoticeErrorParameters(), true); AgentInfo.getInstance().agentStatTrigger(false); } - readSkipScan(); } - private void readSkipScan() { - agentMode.getSkipScan().setApis(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_API, Collections.emptyList())); - agentMode.getSkipScan().getParameters().setQuery(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_QUERY, Collections.emptyList())); - agentMode.getSkipScan().getParameters().setHeader(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_HEADER, Collections.emptyList())); - agentMode.getSkipScan().getParameters().setBody(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_BODY, Collections.emptyList())); - agentMode.getSkipScan().getIastDetectionCategory().setInsecureSettingsEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INSECURE_SETTINGS, true)); - agentMode.getSkipScan().getIastDetectionCategory().setInvalidFileAccessEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INVALID_FILE_ACCESS, true)); - agentMode.getSkipScan().getIastDetectionCategory().setSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SQL_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setNoSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_NOSQL_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setLdapInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_LDAP_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setJavascriptInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_JAVASCRIPT_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setCommandInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_COMMAND_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setXpathInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_XPATH_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setSsrfEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SSRF, true)); - agentMode.getSkipScan().getIastDetectionCategory().setRxssEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_RXSS, true)); - agentMode.getSkipScan().getIastDetectionCategory().generateDisabledCategoriesCSV(); + private void readSkipScan() throws RestrictionModeException { + try { + agentMode.getSkipScan().setApis(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_API, Collections.emptyList())); + agentMode.getSkipScan().getParameters().setQuery(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_QUERY, Collections.emptyList())); + agentMode.getSkipScan().getParameters().setHeader(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_HEADER, Collections.emptyList())); + agentMode.getSkipScan().getParameters().setBody(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_BODY, Collections.emptyList())); + agentMode.getSkipScan().getIastDetectionCategory().setInsecureSettingsEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INSECURE_SETTINGS, true)); + agentMode.getSkipScan().getIastDetectionCategory().setInvalidFileAccessEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INVALID_FILE_ACCESS, true)); + agentMode.getSkipScan().getIastDetectionCategory().setSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SQL_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setNoSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_NOSQL_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setLdapInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_LDAP_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setJavascriptInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_JAVASCRIPT_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setCommandInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_COMMAND_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setXpathInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_XPATH_INJECTION, true)); + agentMode.getSkipScan().getIastDetectionCategory().setSsrfEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SSRF, true)); + agentMode.getSkipScan().getIastDetectionCategory().setRxssEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_RXSS, true)); + agentMode.getSkipScan().getIastDetectionCategory().generateDisabledCategoriesCSV(); + } catch (ClassCastException | NumberFormatException e){ + throw new RestrictionModeException("Invalid Security Configuration " + e.getMessage(), e); + } } private void readScanSchedule() throws RestrictionModeException { - agentMode.getScanSchedule().setDelay(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_DELAY, 0)); - agentMode.getScanSchedule().setDuration(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_DURATION, 0)); - agentMode.getScanSchedule().setSchedule(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_SCHEDULE, StringUtils.EMPTY)); - if(agentMode.getScanSchedule().getDelay() > 0) { - agentMode.getScanSchedule().setNextScanTime(new Date(Instant.now().toEpochMilli() + TimeUnit.MINUTES.toMillis(agentMode.getScanSchedule().getDelay()))); - } else if(StringUtils.isNotBlank(agentMode.getScanSchedule().getSchedule())) { - if(CronExpression.isValidExpression(agentMode.getScanSchedule().getSchedule())){ - try { - agentMode.getScanSchedule().setNextScanTime(new CronExpression(agentMode.getScanSchedule().getSchedule()).getTimeAfter(new Date())); - } catch (ParseException e) { - throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE, e); + try { + agentMode.getScanSchedule().setDelay(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_DELAY, 0)); + agentMode.getScanSchedule().setDuration(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_DURATION, 0)); + agentMode.getScanSchedule().setSchedule(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_SCHEDULE, StringUtils.EMPTY)); + if (agentMode.getScanSchedule().getDelay() > 0) { + agentMode.getScanSchedule().setNextScanTime(new Date(Instant.now().toEpochMilli() + TimeUnit.MINUTES.toMillis(agentMode.getScanSchedule().getDelay()))); + } else if (StringUtils.isNotBlank(agentMode.getScanSchedule().getSchedule())) { + if (CronExpression.isValidExpression(agentMode.getScanSchedule().getSchedule())) { + try { + agentMode.getScanSchedule().setNextScanTime(new CronExpression(agentMode.getScanSchedule().getSchedule()).getTimeAfter(new Date())); + } catch (ParseException e) { + throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE, e); + } + } else { + throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE); } - } else { - throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE); } + } catch (ClassCastException | NumberFormatException e){ + throw new RestrictionModeException("Invalid Security Configuration " + e.getMessage(), e); } } 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 5344ab97d..be08c945e 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 @@ -251,15 +251,20 @@ public boolean refreshState(java.net.URL agentJarURL, Instrumentation instrument /** * restart k2 services **/ - this.agentJarURL = agentJarURL; - this.instrumentation = instrumentation; - if (isInitialised()) { - config.setNRSecurityEnabled(false); - AgentInfo.getInstance().setAgentActive(false); - cancelActiveServiceTasks(); + try { + this.agentJarURL = agentJarURL; + this.instrumentation = instrumentation; + if (isInitialised()) { + config.setNRSecurityEnabled(false); + AgentInfo.getInstance().setAgentActive(false); + cancelActiveServiceTasks(); + } + initialise(); + NewRelic.getAgent().getLogger().log(Level.INFO, "Security refresh was invoked, Security Agent initiation is successful."); + } catch (Exception e){ + NewRelic.getAgent().getLogger().log(Level.SEVERE, "Newrelic Security Startup failed!!!", e); + NewRelic.noticeError(e, customNoticeErrorParameters, true); } - initialise(); - NewRelic.getAgent().getLogger().log(Level.INFO, "Security refresh was invoked, Security Agent initiation is successful."); return true; } From bb427d78f258ccc378205ff487433ae5487cc83a Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 16 Aug 2024 15:00:51 +0530 Subject: [PATCH 092/122] Add feature to collect sample in IAST Scan deactivate mode. Fix default values of IAST scan ignore categories Add feature to schedule via cron expression --- .../newrelic/agent/security/AgentConfig.java | 37 +++-- .../IASTDataTransferRequestProcessor.java | 7 +- .../instrumentator/utils/AgentUtils.java | 16 -- .../agent/security/util/IUtilConstants.java | 1 + .../newrelic/api/agent/security/Agent.java | 155 +++++++++++------- .../security/schema/policy/IASTScan.java | 4 + .../schema/policy/IastDetectionCategory.java | 2 + .../security/schema/policy/ScanSchedule.java | 34 ++++ .../security/schema/policy/SkipScan.java | 3 + 9 files changed, 165 insertions(+), 94 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 d69bd5fbe..bd77424a4 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 @@ -72,7 +72,7 @@ public long instantiate(){ //Set k2 home path boolean validHomePath = setSecurityHomePath(); if(validHomePath) { - System.out.println("New Relic Security Agent: Setting csec home path to directory: " + NR_CSEC_HOME); + System.out.println("New Relic Security Agent: Setting Security home path to directory: " + NR_CSEC_HOME); } isNRSecurityEnabled = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_SECURITY_ENABLED, false); // Set required Group @@ -96,7 +96,8 @@ public long triggerIAST() { try { if(agentMode.getScanSchedule().getNextScanTime() != null) { logger.log(LogLevel.FINER, "Security Agent scan time is set to : " + agentMode.getScanSchedule().getNextScanTime(), AgentConfig.class.getName()); - return agentMode.getScanSchedule().getNextScanTime().getTime() - Instant.now().toEpochMilli(); + long delay = agentMode.getScanSchedule().getNextScanTime().getTime() - Instant.now().toEpochMilli(); + return (delay > 0)? delay : 0; } } catch (Exception e){ NewRelic.noticeError(new RestrictionModeException("Error while calculating next scan time for IAST Restricted Mode", e), Agent.getCustomNoticeErrorParameters(), true); @@ -141,7 +142,7 @@ private void instantiateAgentMode(String groupName) { NewRelic.noticeError(e, Agent.getCustomNoticeErrorParameters(), true); AgentInfo.getInstance().agentStatTrigger(false); } - + logger.log(LogLevel.INFO, String.format("Security Agent Modes and Config : %s", agentMode), AgentConfig.class.getName()); } private void readSkipScan() throws RestrictionModeException { @@ -150,16 +151,16 @@ private void readSkipScan() throws RestrictionModeException { agentMode.getSkipScan().getParameters().setQuery(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_QUERY, Collections.emptyList())); agentMode.getSkipScan().getParameters().setHeader(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_HEADER, Collections.emptyList())); agentMode.getSkipScan().getParameters().setBody(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_BODY, Collections.emptyList())); - agentMode.getSkipScan().getIastDetectionCategory().setInsecureSettingsEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INSECURE_SETTINGS, true)); - agentMode.getSkipScan().getIastDetectionCategory().setInvalidFileAccessEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INVALID_FILE_ACCESS, true)); - agentMode.getSkipScan().getIastDetectionCategory().setSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SQL_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setNoSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_NOSQL_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setLdapInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_LDAP_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setJavascriptInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_JAVASCRIPT_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setCommandInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_COMMAND_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setXpathInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_XPATH_INJECTION, true)); - agentMode.getSkipScan().getIastDetectionCategory().setSsrfEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SSRF, true)); - agentMode.getSkipScan().getIastDetectionCategory().setRxssEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_RXSS, true)); + agentMode.getSkipScan().getIastDetectionCategory().setInsecureSettingsEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INSECURE_SETTINGS, false)); + agentMode.getSkipScan().getIastDetectionCategory().setInvalidFileAccessEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INVALID_FILE_ACCESS, false)); + agentMode.getSkipScan().getIastDetectionCategory().setSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SQL_INJECTION, false)); + agentMode.getSkipScan().getIastDetectionCategory().setNoSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_NOSQL_INJECTION, false)); + agentMode.getSkipScan().getIastDetectionCategory().setLdapInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_LDAP_INJECTION, false)); + agentMode.getSkipScan().getIastDetectionCategory().setJavascriptInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_JAVASCRIPT_INJECTION, false)); + agentMode.getSkipScan().getIastDetectionCategory().setCommandInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_COMMAND_INJECTION, false)); + agentMode.getSkipScan().getIastDetectionCategory().setXpathInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_XPATH_INJECTION, false)); + agentMode.getSkipScan().getIastDetectionCategory().setSsrfEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SSRF, false)); + agentMode.getSkipScan().getIastDetectionCategory().setRxssEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_RXSS, false)); agentMode.getSkipScan().getIastDetectionCategory().generateDisabledCategoriesCSV(); } catch (ClassCastException | NumberFormatException e){ throw new RestrictionModeException("Invalid Security Configuration " + e.getMessage(), e); @@ -171,9 +172,11 @@ private void readScanSchedule() throws RestrictionModeException { agentMode.getScanSchedule().setDelay(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_DELAY, 0)); agentMode.getScanSchedule().setDuration(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_DURATION, 0)); agentMode.getScanSchedule().setSchedule(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_SCHEDULE, StringUtils.EMPTY)); + agentMode.getScanSchedule().setCollectSamples(NewRelic.getAgent().getConfig().getValue(SCAN_TIME_COLLECT_SAMPLES, false)); if (agentMode.getScanSchedule().getDelay() > 0) { agentMode.getScanSchedule().setNextScanTime(new Date(Instant.now().toEpochMilli() + TimeUnit.MINUTES.toMillis(agentMode.getScanSchedule().getDelay()))); } else if (StringUtils.isNotBlank(agentMode.getScanSchedule().getSchedule())) { + agentMode.getScanSchedule().setScheduleOnce(false); if (CronExpression.isValidExpression(agentMode.getScanSchedule().getSchedule())) { try { agentMode.getScanSchedule().setNextScanTime(new CronExpression(agentMode.getScanSchedule().getSchedule()).getTimeAfter(new Date())); @@ -184,6 +187,10 @@ private void readScanSchedule() throws RestrictionModeException { throw new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE); } } + agentMode.getScanSchedule().setDataCollectionTime(agentMode.getScanSchedule().getNextScanTime()); + if(agentMode.getScanSchedule().isCollectSamples()){ + agentMode.getScanSchedule().setNextScanTime(new Date(Instant.now().toEpochMilli())); + } } catch (ClassCastException | NumberFormatException e){ throw new RestrictionModeException("Invalid Security Configuration " + e.getMessage(), e); } @@ -393,10 +400,6 @@ public boolean isNRSecurityEnabled() { return isNRSecurityEnabled; } - public void setNRSecurityEnabled(boolean NRSecurityEnabled) { - isNRSecurityEnabled = NRSecurityEnabled; - } - public String getSecurityHome() { return NR_CSEC_HOME; } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java index c4c732798..c73a1cbf0 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java @@ -156,7 +156,12 @@ public static IASTDataTransferRequestProcessor getInstance() { public void startDataRequestSchedule(long delay, TimeUnit timeUnit){ try { stopDataRequestSchedule(true); - future = executorService.scheduleWithFixedDelay(this::task, 0, delay, timeUnit); + long initialDelay = AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime().toInstant().getEpochSecond() - Instant.now().getEpochSecond(); + if(initialDelay < 0){ + initialDelay = 0; + } + logger.log(LogLevel.INFO, String.format("IAST data pull request is scheduled at %s", AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime()), IASTDataTransferRequestProcessor.class.getName()); + future = executorService.scheduleWithFixedDelay(this::task, initialDelay, delay, timeUnit); } catch (Throwable ignored){} } 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 da5c72381..89f16a195 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 @@ -427,22 +427,6 @@ public static boolean applyPolicy(AgentPolicy newPolicy) { AgentUtils.getInstance().getStatusLogValues().put(POLICY_VERSION, AgentUtils.getInstance().getAgentPolicy().getVersion()); EventSendPool.getInstance().sendEvent(AgentInfo.getInstance().getApplicationInfo()); - // Start IAST data pull if policy allows - if (NewRelicSecurity.getAgent().getCurrentPolicy().getVulnerabilityScan().getEnabled() && - NewRelicSecurity.getAgent().getCurrentPolicy().getVulnerabilityScan().getIastScan().getEnabled() - ) { - IASTDataTransferRequestProcessor.getInstance().startDataRequestSchedule( - NewRelicSecurity.getAgent().getCurrentPolicy() - .getVulnerabilityScan().getIastScan().getProbing().getInterval(), TimeUnit.SECONDS); - logger.logInit( - LogLevel.INFO, - String.format(STARTED_MODULE_LOG, AgentServices.IASTDataPullService.name()), - Agent.class.getName() - ); - } else { - IASTDataTransferRequestProcessor.getInstance().stopDataRequestSchedule(true); - } - return true; } catch (Throwable e) { logger.logInit(LogLevel.SEVERE, IAgentConstants.UNABLE_TO_SET_AGENT_POLICY_DUE_TO_ERROR, e, 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 babebd221..80850f016 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 @@ -11,6 +11,7 @@ public interface IUtilConstants { String SCAN_TIME_DELAY = "security.scan_schedule.delay"; String SCAN_TIME_SCHEDULE = "security.scan_schedule.schedule"; String SCAN_TIME_DURATION = "security.scan_schedule.duration"; + String SCAN_TIME_COLLECT_SAMPLES = "security.scan_schedule.allow_iast_sample_collection"; String SKIP_IAST_SCAN = "security.skip_iast_scan"; String SKIP_IAST_SCAN_API = SKIP_IAST_SCAN + ".api"; 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 be08c945e..fbf5df4a1 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 @@ -4,20 +4,19 @@ import com.newrelic.agent.security.AgentConfig; 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.httpclient.IASTDataTransferRequestProcessor; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.instrumentator.utils.*; import com.newrelic.agent.security.intcodeagent.constants.AgentServices; import com.newrelic.agent.security.intcodeagent.constants.HttpStatusCodes; import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessor; import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessorThreadPool; +import com.newrelic.agent.security.intcodeagent.exceptions.RestrictionModeException; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.filelogging.LogFileHelper; import com.newrelic.agent.security.intcodeagent.models.collectorconfig.AgentMode; import com.newrelic.agent.security.intcodeagent.models.javaagent.*; -import com.newrelic.agent.security.intcodeagent.utils.EncryptorUtils; -import com.newrelic.agent.security.intcodeagent.utils.RestrictionUtility; -import com.newrelic.agent.security.intcodeagent.utils.RuntimeErrorReporter; +import com.newrelic.agent.security.intcodeagent.utils.*; import com.newrelic.api.agent.security.instrumentation.helpers.*; import com.newrelic.api.agent.security.schema.operation.SecureCookieOperationSet; import com.newrelic.api.agent.security.schema.policy.IastDetectionCategory; @@ -27,7 +26,6 @@ import com.newrelic.agent.security.intcodeagent.properties.BuildInfo; import com.newrelic.agent.security.intcodeagent.schedulers.FileCleaner; import com.newrelic.agent.security.intcodeagent.schedulers.SchedulerHelper; -import com.newrelic.agent.security.intcodeagent.utils.CommonUtils; import com.newrelic.agent.security.intcodeagent.websocket.*; import com.newrelic.agent.security.util.IUtilConstants; import com.newrelic.api.agent.NewRelic; @@ -36,6 +34,7 @@ import com.newrelic.api.agent.security.schema.operation.RXSSOperation; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import org.apache.commons.lang3.StringUtils; +import org.java_websocket.framing.CloseFrame; import java.io.File; import java.io.IOException; @@ -43,13 +42,10 @@ import java.lang.instrument.UnmodifiableClassException; import java.net.HttpURLConnection; import java.net.URL; +import java.text.ParseException; import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Properties; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -67,6 +63,7 @@ public class Agent implements SecurityAgent { private static final AtomicBoolean firstEventProcessed = new AtomicBoolean(false); public static final String ERROR_WHILE_GENERATING_TRACE_ID_FOR_CATEGORY_S = "Error while generating trace id for category : %s"; public static final String SKIPPING_THE_API_S_AS_IT_IS_PART_OF_THE_SKIP_SCAN_LIST = "Skipping the API %s as it is part of the skip scan list"; + public static final String INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE = "Invalid cron expression provided for IAST Mode"; private AgentInfo info; @@ -127,61 +124,84 @@ private void triggerNrSecurity() { * */ //NOTE: The bellow call sequence is critical and dependent on each other - logger = FileLoggerThreadPool.getInstance(); - logger.logInit( - LogLevel.INFO, - "[STEP-1] => Security agent is starting", - Agent.class.getName()); - logger.logInit( - LogLevel.INFO, - String.format("[STEP-2] => Generating unique identifier: %s", AgentInfo.getInstance().getApplicationUUID()), AgentInfo.class.getName()); - config.setConfig(CollectorConfigurationUtils.populateCollectorConfig()); - - info.setBuildInfo(readCollectorBuildInfo()); - logger.log(LogLevel.INFO, String.format("CSEC Collector build info : %s", info.getBuildInfo()), this.getClass().getName()); - - logger.logInit( - LogLevel.INFO, - "[STEP-3] => Gathering information about the application", - this.getClass().getName()); - logger.logInit(LogLevel.INFO, !config.getAgentMode().getSkipScan().getIastDetectionCategory().getInsecureSettingsEnabled()? - "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()); + try { + logger = FileLoggerThreadPool.getInstance(); + logger.logInit( + LogLevel.INFO, + "[STEP-1] => Security agent is starting", + Agent.class.getName()); + logger.logInit( + LogLevel.INFO, + String.format("[STEP-2] => Generating unique identifier: %s", AgentInfo.getInstance().getApplicationUUID()), AgentInfo.class.getName()); + config.setConfig(CollectorConfigurationUtils.populateCollectorConfig()); + + info.setBuildInfo(readCollectorBuildInfo()); + logger.log(LogLevel.INFO, String.format("CSEC Collector build info : %s", info.getBuildInfo()), this.getClass().getName()); + + logger.logInit( + LogLevel.INFO, + "[STEP-3] => Gathering information about the application", + this.getClass().getName()); + logger.logInit(LogLevel.INFO, !config.getAgentMode().getSkipScan().getIastDetectionCategory().getInsecureSettingsEnabled() ? + "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()); + info.initialiseHC(); + config.populateAgentPolicy(); + config.populateAgentPolicyParameters(); + config.setupSnapshotDir(); + info.initStatusLogValues(); + setInitialised(true); + populateLinkingMetadata(); + populateApplicationTmpDir(); + startSecurityServices(); + info.agentStatTrigger(true); + //Schedule NR csec shutdown if required + scheduleShutdownTrigger(); + } catch (Exception e){ + e.printStackTrace(); } - info.setIdentifier(ApplicationInfoUtils.envDetection()); - ApplicationInfoUtils.continueIdentifierProcessing(info.getIdentifier(), config.getConfig()); - info.generateAppInfo(config.getConfig()); - info.initialiseHC(); - config.populateAgentPolicy(); - config.populateAgentPolicyParameters(); - config.setupSnapshotDir(); - info.initStatusLogValues(); - setInitialised(true); - populateLinkingMetadata(); - populateApplicationTmpDir(); - startSecurityServices(); - info.agentStatTrigger(true); - //Schedule NR csec shutdown if required - scheduleShutdownTrigger(); } private void scheduleShutdownTrigger() { if(AgentConfig.getInstance().getAgentMode().getScanSchedule().getDuration() > 0) { int duration = AgentConfig.getInstance().getAgentMode().getScanSchedule().getDuration(); Instant now = Instant.now(); + if(AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime() != null){ + now = AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime().toInstant(); + } Instant shutdownInstant = now.plus(duration, ChronoUnit.MINUTES); - long shutdownTime = shutdownInstant.getEpochSecond() - now.getEpochSecond(); - SchedulerHelper.getInstance().scheduleIastTrigger(this::IastShutdown, shutdownTime, TimeUnit.SECONDS); + long shutdownTime = shutdownInstant.getEpochSecond() - Instant.now().getEpochSecond(); + SchedulerHelper.getInstance().scheduleIastTrigger(this::IastDeactivate, shutdownTime, TimeUnit.SECONDS); } } - private void IastShutdown() { - if(ControlCommandProcessor.getIastReplayRequestMsgReceiveTime().isBefore(Instant.now().minus(5, ChronoUnit.MINUTES))){ + private void IastDeactivate() { + if(ControlCommandProcessor.getIastReplayRequestMsgReceiveTime().isAfter(Instant.now().minus(5, ChronoUnit.MINUTES))){ logger.log(LogLevel.WARNING, "IAST scan is still in progress, may have undetected vulnerabilities. Please increase scan duration and restart application.", Agent.class.getName()); } - logger.log(LogLevel.INFO, "Scan duration completed, IAST Scan shutting down.", Agent.class.getName()); - InstrumentationUtils.shutdownLogic(); + logger.log(LogLevel.INFO, "Scan duration completed, IAST going under hibernate mode.", Agent.class.getName()); + deactivateSecurity(); + if(!config.getAgentMode().getScanSchedule().isScheduleOnce()){ + try { + config.getAgentMode().getScanSchedule().setNextScanTime(new CronExpression(config.getAgentMode().getScanSchedule().getSchedule()).getTimeAfter(new Date())); + config.getAgentMode().getScanSchedule().setDataCollectionTime(config.getAgentMode().getScanSchedule().getNextScanTime()); + if(config.getAgentMode().getScanSchedule().isCollectSamples()){ + config.getAgentMode().getScanSchedule().setNextScanTime(new Date(Instant.now().toEpochMilli())); + } + long delay = config.triggerIAST(); + SchedulerHelper.getInstance().scheduleIastTrigger(this::triggerNrSecurity, delay, TimeUnit.MILLISECONDS); + } catch (ParseException e) { + System.err.println("[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled."); + NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled. Message :{}", e.getMessage()); + NewRelic.noticeError(new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE, e), Agent.getCustomNoticeErrorParameters(), true); + AgentInfo.getInstance().agentStatTrigger(false); + } + } } private void IastRestrictedShutdown() { @@ -238,6 +258,18 @@ private void startSecurityServices() { Agent.class.getName() ); logger.logInit(LogLevel.INFO, AGENT_INIT_LOG_STEP_FIVE_END, Agent.class.getName()); + // Start IAST data pull if policy allows + if (config.getAgentMode().getIastScan().getEnabled()) { + IASTDataTransferRequestProcessor.getInstance().startDataRequestSchedule( + config.getAgentMode().getIastScan().getProbing().getInterval(), TimeUnit.SECONDS); + logger.logInit( + LogLevel.INFO, + String.format(STARTED_MODULE_LOG, AgentServices.IASTDataPullService.name()), + Agent.class.getName() + ); + } else { + IASTDataTransferRequestProcessor.getInstance().stopDataRequestSchedule(true); + } } @@ -255,7 +287,6 @@ public boolean refreshState(java.net.URL agentJarURL, Instrumentation instrument this.agentJarURL = agentJarURL; this.instrumentation = instrumentation; if (isInitialised()) { - config.setNRSecurityEnabled(false); AgentInfo.getInstance().setAgentActive(false); cancelActiveServiceTasks(); } @@ -286,7 +317,6 @@ private void cancelActiveServiceTasks() { @Override public boolean deactivateSecurity() { if(isInitialised()) { - config.setNRSecurityEnabled(false); deactivateSecurityServices(); } return true; @@ -300,12 +330,17 @@ private void deactivateSecurityServices(){ * 3. event pool * 4. HealthCheck **/ - InstrumentationUtils.shutdownLogic(); - HealthCheckScheduleThread.getInstance().cancelTask(true); - FileCleaner.cancelTask(); - WSClient.shutDownWSClientAbnormal(true); - WSReconnectionST.shutDownPool(); - EventSendPool.shutDownPool(); +// InstrumentationUtils.shutdownLogic(); + IASTDataTransferRequestProcessor.getInstance().stopDataRequestSchedule(true); + if(!config.getAgentMode().getScanSchedule().isCollectSamples()) { + AgentInfo.getInstance().setAgentActive(false); + HealthCheckScheduleThread.getInstance().cancelTask(true); + FileCleaner.cancelTask(); + WSReconnectionST.cancelTask(true); + WSClient.shutDownWSClient(true, CloseFrame.NORMAL, "Deactivating Security Agent"); + } + + } @Override diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java index d5259effb..cadba8ae5 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java @@ -1,11 +1,15 @@ package com.newrelic.api.agent.security.schema.policy; +import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; + public class IASTScan { private Boolean enabled = true; private Probing probing = new Probing(); + @JsonIgnore private Boolean restricted = false; + @JsonIgnore private RestrictionCriteria restrictionCriteria = new RestrictionCriteria(); /** diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java index c555dda1d..25d0439d4 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IastDetectionCategory.java @@ -1,6 +1,7 @@ package com.newrelic.api.agent.security.schema.policy; import com.newrelic.api.agent.security.schema.VulnerabilityCaseType; +import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; public class IastDetectionCategory { @@ -16,6 +17,7 @@ public class IastDetectionCategory { Boolean xpathInjectionEnabled = false; Boolean ssrfEnabled = false; + @JsonIgnore private String disabledCategoriesCSV; public IastDetectionCategory() { diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanSchedule.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanSchedule.java index 75084afb0..22cf5732d 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanSchedule.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/ScanSchedule.java @@ -1,5 +1,7 @@ package com.newrelic.api.agent.security.schema.policy; +import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; + import java.util.Date; public class ScanSchedule { @@ -12,6 +14,14 @@ public class ScanSchedule { private int delay = 0; + private boolean collectSamples = false; + + @JsonIgnore + private Date dataCollectionTime; + + @JsonIgnore + private boolean scheduleOnce = true; + public ScanSchedule() { } @@ -46,4 +56,28 @@ public int getDelay() { public void setDelay(int delay) { this.delay = delay; } + + public boolean isCollectSamples() { + return collectSamples; + } + + public void setCollectSamples(boolean collectSamples) { + this.collectSamples = collectSamples; + } + + public Date getDataCollectionTime() { + return dataCollectionTime; + } + + public void setDataCollectionTime(Date dataCollectionTime) { + this.dataCollectionTime = dataCollectionTime; + } + + public boolean isScheduleOnce() { + return scheduleOnce; + } + + public void setScheduleOnce(boolean scheduleOnce) { + this.scheduleOnce = scheduleOnce; + } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScan.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScan.java index 042f28366..b89eed6b4 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScan.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/SkipScan.java @@ -1,5 +1,7 @@ package com.newrelic.api.agent.security.schema.policy; +import com.newrelic.api.agent.security.schema.annotations.JsonIgnore; + import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; @@ -7,6 +9,7 @@ public class SkipScan { private List apis = new ArrayList<>(); + @JsonIgnore private List apiRoutes = new ArrayList<>(); private SkipScanParameters parameters = new SkipScanParameters(); From d29056c21eace6fa6e2771e3d7991e22e9e89c44 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 16 Aug 2024 17:02:44 +0530 Subject: [PATCH 093/122] Null checks for NextScanTime and fir for nr logging IAE. --- .../java/com/newrelic/agent/security/AgentConfig.java | 2 +- .../httpclient/IASTDataTransferRequestProcessor.java | 8 ++++++-- .../main/java/com/newrelic/api/agent/security/Agent.java | 2 +- 3 files changed, 8 insertions(+), 4 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 bd77424a4..2ec582429 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 @@ -138,7 +138,7 @@ private void instantiateAgentMode(String groupName) { readSkipScan(); } catch (RestrictionModeException e){ System.err.println("[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled."); - NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled. Message :{}", e.getMessage()); + NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled. Message : {0}", e.getMessage()); NewRelic.noticeError(e, Agent.getCustomNoticeErrorParameters(), true); AgentInfo.getInstance().agentStatTrigger(false); } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java index c73a1cbf0..4dcb65480 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java @@ -156,17 +156,21 @@ public static IASTDataTransferRequestProcessor getInstance() { public void startDataRequestSchedule(long delay, TimeUnit timeUnit){ try { stopDataRequestSchedule(true); - long initialDelay = AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime().toInstant().getEpochSecond() - Instant.now().getEpochSecond(); + long initialDelay = 0; + if(AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime() != null) { + initialDelay = AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime().toInstant().getEpochSecond() - Instant.now().getEpochSecond(); + } if(initialDelay < 0){ initialDelay = 0; } - logger.log(LogLevel.INFO, String.format("IAST data pull request is scheduled at %s", AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime()), IASTDataTransferRequestProcessor.class.getName()); + logger.log(LogLevel.INFO, String.format("IAST data pull request is scheduled at %s, after delay of %s seconds", AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime(), initialDelay), IASTDataTransferRequestProcessor.class.getName()); future = executorService.scheduleWithFixedDelay(this::task, initialDelay, delay, timeUnit); } catch (Throwable ignored){} } public void stopDataRequestSchedule(boolean force){ try { + logger.log(LogLevel.FINER, "deactivating data pull request until reschedule.", IASTDataTransferRequestProcessor.class.getName()); if (this.future != null) { future.cancel(force); future = null; 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 fbf5df4a1..445ba72d0 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 @@ -197,7 +197,7 @@ private void IastDeactivate() { SchedulerHelper.getInstance().scheduleIastTrigger(this::triggerNrSecurity, delay, TimeUnit.MILLISECONDS); } catch (ParseException e) { System.err.println("[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled."); - NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled. Message :{}", e.getMessage()); + NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled. Message :{0}", e.getMessage()); NewRelic.noticeError(new RestrictionModeException(INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE, e), Agent.getCustomNoticeErrorParameters(), true); AgentInfo.getInstance().agentStatTrigger(false); } From 9c7fe754e040938185459e1825901fd6a15177a7 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 16 Aug 2024 17:42:19 +0530 Subject: [PATCH 094/122] Shutdown agent if config is incorrect Prevent multiple schedules of IAST trigger --- .../newrelic/agent/security/AgentConfig.java | 13 +++++++---- .../schedulers/SchedulerHelper.java | 9 +++++++- .../newrelic/api/agent/security/Agent.java | 23 ++++++++++++++----- 3 files changed, 33 insertions(+), 12 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 2ec582429..cfe4d9c0e 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 @@ -68,7 +68,7 @@ public class AgentConfig { private AgentConfig(){ } - public long instantiate(){ + public long instantiate() throws RestrictionModeException { //Set k2 home path boolean validHomePath = setSecurityHomePath(); if(validHomePath) { @@ -92,7 +92,7 @@ public long instantiate(){ return triggerIAST(); } - public long triggerIAST() { + public long triggerIAST() throws RestrictionModeException { try { if(agentMode.getScanSchedule().getNextScanTime() != null) { logger.log(LogLevel.FINER, "Security Agent scan time is set to : " + agentMode.getScanSchedule().getNextScanTime(), AgentConfig.class.getName()); @@ -100,15 +100,16 @@ public long triggerIAST() { return (delay > 0)? delay : 0; } } catch (Exception e){ - NewRelic.noticeError(new RestrictionModeException("Error while calculating next scan time for IAST Restricted Mode", e), Agent.getCustomNoticeErrorParameters(), true); + RestrictionModeException restrictionModeException = new RestrictionModeException("Error while calculating next scan time for IAST Restricted Mode", e); + NewRelic.noticeError(restrictionModeException, Agent.getCustomNoticeErrorParameters(), true); System.err.println("[NR-CSEC-JA] Error while calculating next scan time for IAST Restricted Mode. IAST Restricted Mode will be disabled."); NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while calculating next scan time for IAST Restricted Mode. IAST Restricted Mode will be disabled."); - return Long.MAX_VALUE; + throw restrictionModeException; } return 0; } - private void instantiateAgentMode(String groupName) { + private void instantiateAgentMode(String groupName) throws RestrictionModeException { this.agentMode = new AgentMode(groupName); switch (groupName){ case IAST: @@ -126,6 +127,7 @@ private void instantiateAgentMode(String groupName) { NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled."); NewRelic.noticeError(e, Agent.getCustomNoticeErrorParameters(), true); AgentInfo.getInstance().agentStatTrigger(false); + throw e; } break; default: @@ -141,6 +143,7 @@ private void instantiateAgentMode(String groupName) { NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled. Message : {0}", e.getMessage()); NewRelic.noticeError(e, Agent.getCustomNoticeErrorParameters(), true); AgentInfo.getInstance().agentStatTrigger(false); + throw e; } logger.log(LogLevel.INFO, String.format("Security Agent Modes and Config : %s", agentMode), AgentConfig.class.getName()); } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java index 8568a08a1..e51f0659a 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java @@ -11,6 +11,7 @@ public class SchedulerHelper { + public static final String IAST_TRIGGER = "IastTrigger"; private final ScheduledExecutorService commonExecutor; private SchedulerHelper() { @@ -38,7 +39,13 @@ public static SchedulerHelper getInstance() { private final Map> scheduledFutureMap = new ConcurrentHashMap<>(); public ScheduledFuture scheduleIastTrigger(Runnable runnable, long initialDelay, TimeUnit unit) { - return commonExecutor.schedule(runnable, initialDelay, unit); + if(scheduledFutureMap.containsKey(IAST_TRIGGER)){ + ScheduledFuture currentFuture = scheduledFutureMap.get(IAST_TRIGGER); + currentFuture.cancel(false); + } + ScheduledFuture future = commonExecutor.schedule(runnable, initialDelay, unit); + scheduledFutureMap.put(IAST_TRIGGER, future); + return future; } public ScheduledFuture scheduleHealthCheck(Runnable command, 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 445ba72d0..2fd960bb8 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 @@ -103,8 +103,7 @@ public static Map getCustomNoticeErrorParameters() { return customNoticeErrorParameters; } - private void initialise() { - + private void initialise() throws RestrictionModeException { if (!isInitialised()) { config = AgentConfig.getInstance(); info = AgentInfo.getInstance(); @@ -163,7 +162,8 @@ private void triggerNrSecurity() { //Schedule NR csec shutdown if required scheduleShutdownTrigger(); } catch (Exception e){ - e.printStackTrace(); + NewRelic.getAgent().getLogger().log(Level.SEVERE, "[NR-CSEC-JA] Deactivating NewRelic Security Agent due to {0}", e.getMessage()); + NewRelic.noticeError(e, customNoticeErrorParameters, true); } } @@ -195,6 +195,9 @@ private void IastDeactivate() { } long delay = config.triggerIAST(); SchedulerHelper.getInstance().scheduleIastTrigger(this::triggerNrSecurity, delay, TimeUnit.MILLISECONDS); + } catch (RestrictionModeException | SecurityException exception){ + NewRelic.getAgent().getLogger().log(Level.SEVERE, "[NR-CSEC-JA] Deactivating NewRelic Security Agent due to {0}", exception.getMessage()); + NewRelic.noticeError(exception, customNoticeErrorParameters, true); } catch (ParseException e) { System.err.println("[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled."); NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled. Message :{0}", e.getMessage()); @@ -205,9 +208,14 @@ private void IastDeactivate() { } private void IastRestrictedShutdown() { - InstrumentationUtils.shutdownLogic(); - long delay = config.triggerIAST(); - SchedulerHelper.getInstance().scheduleIastTrigger(this::triggerNrSecurity, delay, TimeUnit.MILLISECONDS); + try { + InstrumentationUtils.shutdownLogic(); + long delay = config.triggerIAST(); + SchedulerHelper.getInstance().scheduleIastTrigger(this::triggerNrSecurity, delay, TimeUnit.MILLISECONDS); + } catch (RestrictionModeException | SecurityException exception){ + NewRelic.getAgent().getLogger().log(Level.SEVERE, "[NR-CSEC-JA] Deactivating NewRelic Security Agent due to {0}", exception.getMessage()); + NewRelic.noticeError(exception, customNoticeErrorParameters, true); + } } private void populateApplicationTmpDir() { @@ -292,6 +300,9 @@ public boolean refreshState(java.net.URL agentJarURL, Instrumentation instrument } initialise(); NewRelic.getAgent().getLogger().log(Level.INFO, "Security refresh was invoked, Security Agent initiation is successful."); + } catch (RestrictionModeException | SecurityException exception){ + NewRelic.getAgent().getLogger().log(Level.SEVERE, "[NR-CSEC-JA] Deactivating NewRelic Security Agent due to {0}", exception.getMessage()); + NewRelic.noticeError(exception, customNoticeErrorParameters, true); } catch (Exception e){ NewRelic.getAgent().getLogger().log(Level.SEVERE, "Newrelic Security Startup failed!!!", e); NewRelic.noticeError(e, customNoticeErrorParameters, true); From f42659e577c0c26842307342b0919cf47a5b697f Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 20 Aug 2024 09:56:13 +0530 Subject: [PATCH 095/122] Fix jtds, postgress lock acquire case type. Upgrade pool cleanups and reset --- .../jdbc/JtdsStatement_Instrumentation.java | 22 ++++++++--------- .../jdbc/PgStatement_Instrumentation.java | 16 ++++++------- .../dispatcher/DispatcherPool.java | 1 + .../ControlCommandProcessorThreadPool.java | 14 +++++++++++ .../intcodeagent/websocket/EventSendPool.java | 1 + .../newrelic/api/agent/security/Agent.java | 24 ++++++++++++------- 6 files changed, 51 insertions(+), 27 deletions(-) diff --git a/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsStatement_Instrumentation.java b/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsStatement_Instrumentation.java index c2f9dc4ee..95d6ad062 100644 --- a/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsStatement_Instrumentation.java +++ b/instrumentation-security/jdbc-jtds-generic/src/main/java/net/sourceforge/jtds/jdbc/JtdsStatement_Instrumentation.java @@ -70,12 +70,12 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { - return GenericHelper.acquireLockIfPossible(httpRequest, JdbcHelper.getNrSecCustomAttribName()); + private boolean acquireLockIfPossible() { + return GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND, JdbcHelper.getNrSecCustomAttribName()); } public ResultSet executeQuery(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_QUERY); @@ -93,7 +93,7 @@ public ResultSet executeQuery(String sql) throws SQLException { } public int executeUpdate(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -111,7 +111,7 @@ public int executeUpdate(String sql) throws SQLException { } public boolean execute(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); @@ -129,7 +129,7 @@ public boolean execute(String sql) throws SQLException { } public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -148,7 +148,7 @@ public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -166,7 +166,7 @@ public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { } public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); @@ -184,7 +184,7 @@ public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { } public int executeUpdate(String sql, String[] columnNames) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -202,7 +202,7 @@ public int executeUpdate(String sql, String[] columnNames) throws SQLException { } public boolean execute(String sql, String[] columnNames) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); @@ -221,7 +221,7 @@ public boolean execute(String sql, String[] columnNames) throws SQLException { public boolean execute(String sql, int[] columnIndexes) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); diff --git a/instrumentation-security/jdbc-postgresql-9.4.1207/src/main/java/org/postgresql/jdbc/PgStatement_Instrumentation.java b/instrumentation-security/jdbc-postgresql-9.4.1207/src/main/java/org/postgresql/jdbc/PgStatement_Instrumentation.java index f27cb4069..e032d4204 100644 --- a/instrumentation-security/jdbc-postgresql-9.4.1207/src/main/java/org/postgresql/jdbc/PgStatement_Instrumentation.java +++ b/instrumentation-security/jdbc-postgresql-9.4.1207/src/main/java/org/postgresql/jdbc/PgStatement_Instrumentation.java @@ -84,12 +84,12 @@ private void releaseLock() { } catch (Throwable ignored) {} } - private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { - return GenericHelper.acquireLockIfPossible(httpRequest, JdbcHelper.getNrSecCustomAttribName()); + private boolean acquireLockIfPossible() { + return GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND, JdbcHelper.getNrSecCustomAttribName()); } public ResultSet executeQuery() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -110,7 +110,7 @@ public ResultSet executeQuery() throws SQLException { } public ResultSet executeQuery(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_QUERY); @@ -128,7 +128,7 @@ public ResultSet executeQuery(String sql) throws SQLException { } public int executeUpdate() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -149,7 +149,7 @@ public int executeUpdate() throws SQLException { } public int executeUpdate(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -167,7 +167,7 @@ public int executeUpdate(String sql) throws SQLException { } public boolean execute() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -189,7 +189,7 @@ public boolean execute() throws SQLException { @Trace(leaf = true) public boolean execute(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java index fe9498539..0f9db44a7 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/dispatcher/DispatcherPool.java @@ -269,5 +269,6 @@ public void shutDownThreadPoolExecutor() { public void reset() { executor.getQueue().clear(); + executor.purge(); } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java index 0ef0dcd89..badd1c22a 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java @@ -119,6 +119,20 @@ public static ControlCommandProcessorThreadPool getInstance() { return instance; } + public static void clearAllTasks() { + if (instance != null) { + instance.clearAllTasks(true); + } + } + + private void clearAllTasks(boolean force) { + executor.getQueue().clear(); + executor.purge(); + if(force) { + + } + } + public static void shutDownPool() { if (instance != null) { instance.shutDownThreadPoolExecutor(); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java index ab9dc3650..f517a9ad1 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java @@ -177,5 +177,6 @@ public ThreadPoolExecutor getExecutor() { public void reset() { executor.getQueue().clear(); + executor.purge(); } } 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 2fd960bb8..3aa31e43d 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 @@ -5,6 +5,7 @@ import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.dispatcher.DispatcherPool; import com.newrelic.agent.security.instrumentator.httpclient.IASTDataTransferRequestProcessor; +import com.newrelic.agent.security.instrumentator.httpclient.RestRequestThreadPool; import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance; import com.newrelic.agent.security.instrumentator.utils.*; import com.newrelic.agent.security.intcodeagent.constants.AgentServices; @@ -321,7 +322,7 @@ private void cancelActiveServiceTasks() { HealthCheckScheduleThread.getInstance().cancelTask(true); WSReconnectionST.cancelTask(true); FileCleaner.cancelTask(); - ControlCommandProcessorThreadPool.shutDownPool(); + ControlCommandProcessorThreadPool.clearAllTasks(); } @@ -334,18 +335,25 @@ public boolean deactivateSecurity() { } private void deactivateSecurityServices(){ - /** - * ShutDown following - * 1. policy + policy parameter - * 2. websocket - * 3. event pool - * 4. HealthCheck - **/ + /* + ShutDown following + 1. policy + policy parameter + 2. websocket + 3. event pool + 4. HealthCheck + */ // InstrumentationUtils.shutdownLogic(); IASTDataTransferRequestProcessor.getInstance().stopDataRequestSchedule(true); if(!config.getAgentMode().getScanSchedule().isCollectSamples()) { AgentInfo.getInstance().setAgentActive(false); HealthCheckScheduleThread.getInstance().cancelTask(true); + ControlCommandProcessorThreadPool.clearAllTasks(); + RestRequestThreadPool.getInstance().resetIASTProcessing(); + GrpcClientRequestReplayHelper.getInstance().resetIASTProcessing(); + RestRequestThreadPool.getInstance().getRejectedIds().clear(); + GrpcClientRequestReplayHelper.getInstance().getRejectedIds().clear(); + DispatcherPool.getInstance().reset(); + EventSendPool.getInstance().reset(); FileCleaner.cancelTask(); WSReconnectionST.cancelTask(true); WSClient.shutDownWSClient(true, CloseFrame.NORMAL, "Deactivating Security Agent"); From 5408c8718fd96a2213423fea74d6cbbba2673eeb Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 20 Aug 2024 12:13:20 +0530 Subject: [PATCH 096/122] rename flag for always sample collections --- .../java/com/newrelic/agent/security/util/IUtilConstants.java | 2 +- 1 file changed, 1 insertion(+), 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 80850f016..fd126a910 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 @@ -11,7 +11,7 @@ public interface IUtilConstants { String SCAN_TIME_DELAY = "security.scan_schedule.delay"; String SCAN_TIME_SCHEDULE = "security.scan_schedule.schedule"; String SCAN_TIME_DURATION = "security.scan_schedule.duration"; - String SCAN_TIME_COLLECT_SAMPLES = "security.scan_schedule.allow_iast_sample_collection"; + String SCAN_TIME_COLLECT_SAMPLES = "security.scan_schedule.always_sample_traces"; String SKIP_IAST_SCAN = "security.skip_iast_scan"; String SKIP_IAST_SCAN_API = SKIP_IAST_SCAN + ".api"; From ebe8789bd77037563064bf7c9be36dc8c2448907 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 21 Aug 2024 11:13:40 +0530 Subject: [PATCH 097/122] NR-304574: Rate limit the IAST replay requests --- .../httpclient/IASTDataTransferRequestProcessor.java | 7 ++++++- .../com/newrelic/agent/security/util/IUtilConstants.java | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java index 4dcb65480..f1071d4ba 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java @@ -4,6 +4,7 @@ import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.utils.INRSettingsKey; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; +import com.newrelic.agent.security.util.IUtilConstants; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.models.IASTDataTransferRequest; import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; @@ -78,6 +79,9 @@ private void task() { int currentFetchThreshold = NewRelic.getAgent().getConfig() .getValue(SECURITY_POLICY_VULNERABILITY_SCAN_IAST_SCAN_PROBING_THRESHOLD, 300); + int iastFetchInterval = Math.min(Math.max(NewRelic.getAgent().getConfig().getValue(IUtilConstants.IAST_LOAD_INTERVAL, 5), 5), 500); + int fetchRatio = iastFetchInterval/5; + int remainingRecordCapacityRest = RestRequestThreadPool.getInstance().getQueue().remainingCapacity(); int currentRecordBacklogRest = RestRequestThreadPool.getInstance().getQueue().size(); int remainingRecordCapacityGrpc = GrpcClientRequestReplayHelper.getInstance().getRequestQueue().remainingCapacity(); @@ -90,8 +94,9 @@ private void task() { if(!AgentUsageMetric.isRASPProcessingActive()){ batchSize /= 2; } + batchSize /= fetchRatio; - if (batchSize > 100 && remainingRecordCapacity > batchSize) { + if (batchSize > 100/fetchRatio && remainingRecordCapacity > batchSize) { request = new IASTDataTransferRequest(NewRelicSecurity.getAgent().getAgentUUID()); if (AgentConfig.getInstance().getConfig().getCustomerInfo() != null) { request.setAppAccountId(AgentConfig.getInstance().getConfig().getCustomerInfo().getAccountId()); 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 fd126a910..5aec9dcc5 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 @@ -12,6 +12,7 @@ public interface IUtilConstants { String SCAN_TIME_SCHEDULE = "security.scan_schedule.schedule"; String SCAN_TIME_DURATION = "security.scan_schedule.duration"; String SCAN_TIME_COLLECT_SAMPLES = "security.scan_schedule.always_sample_traces"; + String IAST_LOAD_INTERVAL = "security.scan_controllers.iast_load_interval"; String SKIP_IAST_SCAN = "security.skip_iast_scan"; String SKIP_IAST_SCAN_API = SKIP_IAST_SCAN + ".api"; From a729fcac52565b0d17bc710b1755e2347488550d Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 21 Aug 2024 17:31:41 +0530 Subject: [PATCH 098/122] fix for incompatible data type for skip scan parameters --- .../com/newrelic/agent/security/AgentConfig.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 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 cfe4d9c0e..720b08494 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 @@ -31,6 +31,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; import java.util.logging.Level; +import java.util.stream.Collectors; import static com.newrelic.agent.security.util.IUtilConstants.*; @@ -151,9 +152,15 @@ private void instantiateAgentMode(String groupName) throws RestrictionModeExcept private void readSkipScan() throws RestrictionModeException { try { agentMode.getSkipScan().setApis(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_API, Collections.emptyList())); - agentMode.getSkipScan().getParameters().setQuery(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_QUERY, Collections.emptyList())); - agentMode.getSkipScan().getParameters().setHeader(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_HEADER, Collections.emptyList())); - agentMode.getSkipScan().getParameters().setBody(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_BODY, Collections.emptyList())); + agentMode.getSkipScan().getParameters().setQuery(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_QUERY, Collections.emptyList()).stream() + .map(Object::toString) + .collect(Collectors.toList())); + agentMode.getSkipScan().getParameters().setHeader(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_HEADER, Collections.emptyList()).stream() + .map(Object::toString) + .collect(Collectors.toList())); + agentMode.getSkipScan().getParameters().setBody(NewRelic.getAgent().getConfig().getValue(SKIP_IAST_SCAN_PARAMETERS_BODY, Collections.emptyList()).stream() + .map(Object::toString) + .collect(Collectors.toList())); agentMode.getSkipScan().getIastDetectionCategory().setInsecureSettingsEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INSECURE_SETTINGS, false)); agentMode.getSkipScan().getIastDetectionCategory().setInvalidFileAccessEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_INVALID_FILE_ACCESS, false)); agentMode.getSkipScan().getIastDetectionCategory().setSqlInjectionEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_SQL_INJECTION, false)); From 120ff86371ee335a138918156e926b58436a4380 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 22 Aug 2024 11:19:15 +0530 Subject: [PATCH 099/122] Update config fields --- .../newrelic/agent/security/util/IUtilConstants.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 fd126a910..152567f4c 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 @@ -13,12 +13,12 @@ public interface IUtilConstants { String SCAN_TIME_DURATION = "security.scan_schedule.duration"; String SCAN_TIME_COLLECT_SAMPLES = "security.scan_schedule.always_sample_traces"; - String SKIP_IAST_SCAN = "security.skip_iast_scan"; + String SKIP_IAST_SCAN = "security.exclude_from_iast_scan"; String SKIP_IAST_SCAN_API = SKIP_IAST_SCAN + ".api"; - String SKIP_IAST_SCAN_PARAMETERS = SKIP_IAST_SCAN + ".parameters"; - String SKIP_IAST_SCAN_PARAMETERS_HEADER = SKIP_IAST_SCAN + ".parameters.header"; - String SKIP_IAST_SCAN_PARAMETERS_QUERY = SKIP_IAST_SCAN + ".parameters.query"; - String SKIP_IAST_SCAN_PARAMETERS_BODY = SKIP_IAST_SCAN + ".parameters.body"; + String SKIP_IAST_SCAN_PARAMETERS = SKIP_IAST_SCAN + ".http_request_parameters"; + String SKIP_IAST_SCAN_PARAMETERS_HEADER = SKIP_IAST_SCAN + ".http_request_parameters.header"; + String SKIP_IAST_SCAN_PARAMETERS_QUERY = SKIP_IAST_SCAN + ".http_request_parameters.query"; + String SKIP_IAST_SCAN_PARAMETERS_BODY = SKIP_IAST_SCAN + ".http_request_parameters.body"; String SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY = SKIP_IAST_SCAN + ".iast_detection_category"; String SKIP_INSECURE_SETTINGS = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".insecure_settings"; String SKIP_INVALID_FILE_ACCESS = SKIP_IAST_SCAN_PARAMETERS_IAST_DETECTION_CATEGORY + ".invalid_file_access"; From c361033c37316f2c6c8ffc48968cc51839569eee Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 22 Aug 2024 15:32:07 +0530 Subject: [PATCH 100/122] NR-287324: Report API endpoints immediately after 60 seconds, as soon as new endpoints are discovered --- .../agent/security/instrumentator/utils/AgentUtils.java | 1 - .../security/intcodeagent/schedulers/SchedulerHelper.java | 8 ++++++++ .../agent/security/intcodeagent/websocket/WSClient.java | 1 - .../main/java/com/newrelic/api/agent/security/Agent.java | 5 +++++ .../main/java/com/newrelic/api/agent/security/Agent.java | 5 +++++ .../java/com/newrelic/api/agent/security/NoOpAgent.java | 5 ++++- .../com/newrelic/api/agent/security/SecurityAgent.java | 2 ++ .../instrumentation/helpers/URLMappingsHelper.java | 2 ++ 8 files changed, 26 insertions(+), 3 deletions(-) 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 da5c72381..e8926f7d0 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 @@ -667,7 +667,6 @@ 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()); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java index a68025e68..b20f74517 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/schedulers/SchedulerHelper.java @@ -86,4 +86,12 @@ public ScheduledFuture scheduleDailyLogRollover(Runnable command) { return null; } + public void scheduleURLMappingPosting(Runnable runnable) { + if(scheduledFutureMap.containsKey(IAgentConstants.JSON_SEC_APPLICATION_URL_MAPPING)){ + ScheduledFuture future = scheduledFutureMap.get(IAgentConstants.JSON_SEC_APPLICATION_URL_MAPPING); + future.cancel(false); + } + ScheduledFuture future = commonExecutor.schedule(runnable, 60, TimeUnit.SECONDS); + scheduledFutureMap.put(IAgentConstants.JSON_SEC_APPLICATION_URL_MAPPING, future); + } } 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 338fb464d..eaa5ad97c 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 @@ -257,7 +257,6 @@ public void onOpen(ServerHandshake handshakedata) { WSUtils.getInstance().notifyAll(); } WSUtils.getInstance().setConnected(true); - AgentUtils.sendApplicationURLMappings(); logger.logInit(LogLevel.INFO, String.format(IAgentConstants.APPLICATION_INFO_SENT_ON_WS_CONNECT, AgentInfo.getInstance().getApplicationInfo()), WSClient.class.getName()); } 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 f0241ac02..9aad9a97c 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 @@ -956,4 +956,9 @@ public boolean recordExceptions(SecurityMetaData securityMetaData, Throwable exc return RuntimeErrorReporter.getInstance().addApplicationRuntimeError(applicationRuntimeError); } + @Override + public void reportURLMapping() { + SchedulerHelper.getInstance().scheduleURLMappingPosting(AgentUtils::sendApplicationURLMappings); + } + } \ No newline at end of file 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 3f47b0954..a16eaf983 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 @@ -211,4 +211,9 @@ public void reportApplicationRuntimeError(SecurityMetaData securityMetaData, Thr public boolean recordExceptions(SecurityMetaData securityMetaData, Throwable exception) { return false; } + + @Override + public void reportURLMapping() { + + } } \ No newline at end of file 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 d5e0f6e74..7c6db73b3 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 @@ -7,7 +7,6 @@ package com.newrelic.api.agent.security; -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; @@ -142,5 +141,9 @@ public boolean recordExceptions(SecurityMetaData securityMetaData, Throwable exc return false; } + @Override + public void reportURLMapping() { + + } } 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 82b573974..a0b9627f6 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 @@ -75,4 +75,6 @@ void reportIASTScanFailure(SecurityMetaData securityMetaData, String apiId, Thro void reportApplicationRuntimeError(SecurityMetaData securityMetaData, Throwable exception); boolean recordExceptions(SecurityMetaData securityMetaData, Throwable exception); + + void reportURLMapping(); } 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 9a045a8e2..ee8aa8315 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 @@ -1,5 +1,6 @@ package com.newrelic.api.agent.security.instrumentation.helpers; +import com.newrelic.api.agent.security.NewRelicSecurity; import com.newrelic.api.agent.security.schema.ApplicationURLMapping; import com.newrelic.api.agent.security.schema.RouteSegment; import com.newrelic.api.agent.security.schema.RouteSegments; @@ -63,6 +64,7 @@ public static void addApplicationURLMapping(ApplicationURLMapping mapping) { if (mapping.getHandler() != null){ handlers.add(mapping.getHandler().hashCode()); } + NewRelicSecurity.getAgent().reportURLMapping(); } private synchronized static void generateRouteSegments(String endpoint) { From 7b6e9c878f95af472d6fe73a40058dc5426ba5c2 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 23 Aug 2024 13:43:40 +0530 Subject: [PATCH 101/122] NR-304574: Rate limit the IAST replay requests the default value is 3600 replay req. per min --- .../IASTDataTransferRequestProcessor.java | 21 ++++++++++++------- .../agent/security/util/IUtilConstants.java | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java index f1071d4ba..511ca2282 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java @@ -3,6 +3,7 @@ import com.newrelic.agent.security.AgentConfig; import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.utils.INRSettingsKey; +import com.newrelic.agent.security.intcodeagent.exceptions.RestrictionModeException; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.util.IUtilConstants; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -29,8 +30,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import static com.newrelic.agent.security.instrumentator.utils.INRSettingsKey.SECURITY_POLICY_VULNERABILITY_SCAN_IAST_SCAN_PROBING_THRESHOLD; - public class IASTDataTransferRequestProcessor { private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); public static final String UNABLE_TO_SEND_IAST_DATA_REQUEST_DUE_TO_ERROR_S_S = "Unable to send IAST data request due to error: %s : %s"; @@ -48,6 +47,8 @@ public class IASTDataTransferRequestProcessor { private final AtomicLong lastFuzzCCTimestamp = new AtomicLong(); + private int currentFetchThresholdPerMin = 3600; + private void task() { IASTDataTransferRequest request = null; try { @@ -76,11 +77,12 @@ private void task() { return; } - int currentFetchThreshold = NewRelic.getAgent().getConfig() - .getValue(SECURITY_POLICY_VULNERABILITY_SCAN_IAST_SCAN_PROBING_THRESHOLD, 300); + int currentFetchThreshold = currentFetchThresholdPerMin/12; + if (currentFetchThreshold <= 0){ + return; + } - int iastFetchInterval = Math.min(Math.max(NewRelic.getAgent().getConfig().getValue(IUtilConstants.IAST_LOAD_INTERVAL, 5), 5), 500); - int fetchRatio = iastFetchInterval/5; + int fetchRatio = 300/currentFetchThreshold; int remainingRecordCapacityRest = RestRequestThreadPool.getInstance().getQueue().remainingCapacity(); int currentRecordBacklogRest = RestRequestThreadPool.getInstance().getQueue().size(); @@ -94,7 +96,6 @@ private void task() { if(!AgentUsageMetric.isRASPProcessingActive()){ batchSize /= 2; } - batchSize /= fetchRatio; if (batchSize > 100/fetchRatio && remainingRecordCapacity > batchSize) { request = new IASTDataTransferRequest(NewRelicSecurity.getAgent().getAgentUUID()); @@ -168,6 +169,12 @@ public void startDataRequestSchedule(long delay, TimeUnit timeUnit){ if(initialDelay < 0){ initialDelay = 0; } + // IAST Scan Rate per minute with range [12, 3600]; default 3600 replay requests will be replayed per minute + try { + currentFetchThresholdPerMin = Math.min(Math.max(NewRelic.getAgent().getConfig().getValue(IUtilConstants.SCAN_REQUEST_RATE_LIMIT, 3600), 12), 3600); + } catch (Exception e) { + logger.log(LogLevel.WARNING, String.format("Error while reading Configuration security.scan_request_rate_limit : %s, Using default value %s replay request per min.", e.getMessage(), currentFetchThresholdPerMin), e, this.getClass().getName()); + } logger.log(LogLevel.INFO, String.format("IAST data pull request is scheduled at %s, after delay of %s seconds", AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime(), initialDelay), IASTDataTransferRequestProcessor.class.getName()); future = executorService.scheduleWithFixedDelay(this::task, initialDelay, delay, timeUnit); } catch (Throwable ignored){} 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 0c62b114d..4f5c1ac48 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 @@ -12,7 +12,7 @@ public interface IUtilConstants { String SCAN_TIME_SCHEDULE = "security.scan_schedule.schedule"; String SCAN_TIME_DURATION = "security.scan_schedule.duration"; String SCAN_TIME_COLLECT_SAMPLES = "security.scan_schedule.always_sample_traces"; - String IAST_LOAD_INTERVAL = "security.scan_controllers.iast_load_interval"; + String SCAN_REQUEST_RATE_LIMIT = "security.scan_request_rate_limit"; String SKIP_IAST_SCAN = "security.exclude_from_iast_scan"; String SKIP_IAST_SCAN_API = SKIP_IAST_SCAN + ".api"; From e8db0c7093b455dd60a387a589b749aec3bb8ab4 Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 26 Aug 2024 18:54:49 +0530 Subject: [PATCH 102/122] NR-303483: Server Configuration for WebSphere Liberty --- .../build.gradle | 29 +++++++++++++++ .../lib/.gitignore | 2 + .../internal/TCPChannelFactory.java | 37 +++++++++++++++++++ .../helpers/GenericHelper.java | 1 + settings.gradle | 1 + 5 files changed, 70 insertions(+) create mode 100644 instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/build.gradle create mode 100644 instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/lib/.gitignore create mode 100644 instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/src/main/java/com/ibm/ws/tcpchannel/internal/TCPChannelFactory.java diff --git a/instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/build.gradle b/instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/build.gradle new file mode 100644 index 000000000..7312021d2 --- /dev/null +++ b/instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/build.gradle @@ -0,0 +1,29 @@ +dependencies { + implementation(project(":newrelic-security-api")) + implementation("com.newrelic.agent.java:newrelic-api:${nrAPIVersion}") + implementation("com.newrelic.agent.java:newrelic-weaver-api:${nrAPIVersion}") + 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-liberty' } +} + +site { + title 'WebSphere Liberty' + type 'Appserver' + versionOverride '[8.5,)' +} \ No newline at end of file diff --git a/instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/lib/.gitignore b/instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/lib/.gitignore new file mode 100644 index 000000000..c96a04f00 --- /dev/null +++ b/instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/lib/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/src/main/java/com/ibm/ws/tcpchannel/internal/TCPChannelFactory.java b/instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/src/main/java/com/ibm/ws/tcpchannel/internal/TCPChannelFactory.java new file mode 100644 index 000000000..848fb3aeb --- /dev/null +++ b/instrumentation-security/websphere-liberty-profile-environment-8.5.5.5/src/main/java/com/ibm/ws/tcpchannel/internal/TCPChannelFactory.java @@ -0,0 +1,37 @@ +package com.ibm.ws.tcpchannel.internal; + +import com.ibm.websphere.channelfw.ChannelData; +import com.ibm.wsspi.channelfw.Channel; +import com.ibm.wsspi.channelfw.exception.ChannelException; +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 java.util.Map; + +@Weave +public class TCPChannelFactory { + + protected Channel createChannel(final ChannelData channelData) throws ChannelException { + try { + if (channelData.isInbound() && "defaultHttpEndpoint".equals(channelData.getExternalName())) { + Map propertyBag = channelData.getPropertyBag(); + if (propertyBag.containsKey("port")) { + try { + int port = Integer.parseInt((String) propertyBag.get("port")); + NewRelicSecurity.getAgent().setApplicationConnectionConfig(port, "http"); + } catch (NumberFormatException e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SERVER_CONFIG_ERROR, "WEBSPHERE_LIBERTY", e.getMessage()), e, this.getClass().getName()); + } + } else { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SERVER_CONFIG_ERROR, "WEBSPHERE_LIBERTY", null), null, this.getClass().getName()); + } + } else { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.SERVER_CONFIG_ERROR, "WEBSPHERE_LIBERTY", null), null, this.getClass().getName()); + } + } catch (Exception ignored) { + } + return Weaver.callOriginal(); + } +} 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 8d4cf3f0f..c55dbd421 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 @@ -14,6 +14,7 @@ public class GenericHelper { public static final String NR_SEC_CUSTOM_SPRING_REDIS_ATTR = "SPRING-DATA-REDIS"; public static final String REGISTER_OPERATION_EXCEPTION_MESSAGE = "Instrumentation library: %s , error while library instrumented call processing : %s"; + public static final String SERVER_CONFIG_ERROR = "Instrumentation library: %s , error while detecting Server Configuration : %s"; public static final String EXIT_OPERATION_EXCEPTION_MESSAGE = "Instrumentation library: %s , error while generating exit operation: %s"; public static final String SECURITY_EXCEPTION_MESSAGE = "New Relic Security Exception raised for Instrumentation library: %s, reason: %s "; public static final String URI_EXCEPTION_MESSAGE = "Instrumentation library: %s , error while extracting URI : %s"; diff --git a/settings.gradle b/settings.gradle index b3b2cd194..a2b70cb0c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -216,3 +216,4 @@ include 'instrumentation:solr-5.1.0' include 'instrumentation:solr-7.0.0' include 'instrumentation:solr-8.0.0' include 'instrumentation:solr-9.0.0' +include 'instrumentation:websphere-liberty-profile-environment-8.5.5.5' \ No newline at end of file From 8a5dd01888fde1b7b9dbf5077aba41c53a345fd0 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 28 Aug 2024 16:36:52 +0530 Subject: [PATCH 103/122] NR-303615: Fix for API Endpoint reported giving 404 response code --- .../instrumentation/apache/tomcat10/HttpServletHelper.java | 5 +++++ .../instrumentation/apache/tomcat7/HttpServletHelper.java | 5 +++++ .../security/instrumentation/jetty11/HttpServletHelper.java | 5 +++++ .../security/instrumentation/jetty9/HttpServletHelper.java | 5 +++++ .../instrumentation/servlet24/HttpServletHelper.java | 6 +++++- .../instrumentation/servlet30/HttpServletHelper.java | 5 +++++ .../instrumentation/servlet5/HttpServletHelper.java | 5 +++++ .../instrumentation/servlet6/HttpServletHelper.java | 5 +++++ 8 files changed, 40 insertions(+), 1 deletion(-) 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 4979cbab2..f27ae5e0c 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 @@ -4,6 +4,7 @@ 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.schema.StringUtils; import com.newrelic.api.agent.security.utils.logging.LogLevel; import jakarta.servlet.ServletContext; @@ -37,6 +38,10 @@ private static void getJSPMappings(ServletContext servletContext, String dir) { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); for (String path : resourcePaths) { + String entry = StringUtils.removeStart(StringUtils.removeEnd(path, SEPARATOR), StringUtils.SEPARATOR); + if (StringUtils.equalsAny(entry, "META-INF", "WEB-INF")) { + continue; + } if(path.endsWith(SEPARATOR)) { getJSPMappings(servletContext, 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 764334d19..c585c7b6c 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 @@ -4,6 +4,7 @@ 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.schema.StringUtils; import com.newrelic.api.agent.security.utils.logging.LogLevel; import javax.servlet.ServletContext; @@ -36,6 +37,10 @@ private static void getJSPMappings(ServletContext servletContext, String dir) { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); for (String path : resourcePaths) { + String entry = StringUtils.removeStart(StringUtils.removeEnd(path, SEPARATOR), StringUtils.SEPARATOR); + if (StringUtils.equalsAny(entry, "META-INF", "WEB-INF")) { + continue; + } if(path.endsWith(SEPARATOR)) { getJSPMappings(servletContext, 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 e0528d9e7..7d9da5b24 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 @@ -6,6 +6,7 @@ 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.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; @@ -222,6 +223,10 @@ private static void getJSPMappings(ServletContext servletContext, String dir) { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); for (String path : resourcePaths) { + String entry = StringUtils.removeStart(StringUtils.removeEnd(path, SEPARATOR), StringUtils.SEPARATOR); + if (StringUtils.equalsAny(entry, "META-INF", "WEB-INF")) { + continue; + } if(path.endsWith(SEPARATOR)) { getJSPMappings(servletContext, 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 07b87e142..fc7db6108 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 @@ -6,6 +6,7 @@ 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.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; @@ -224,6 +225,10 @@ private static void getJSPMappings(ServletContext servletContext, String dir) { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); for (String path : resourcePaths) { + String entry = StringUtils.removeStart(StringUtils.removeEnd(path, SEPARATOR), StringUtils.SEPARATOR); + if (StringUtils.equalsAny(entry, "META-INF", "WEB-INF")) { + continue; + } if(path.endsWith(SEPARATOR)) { getJSPMappings(servletContext, path); } 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 aa6ceacd9..272fe95d2 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 @@ -5,6 +5,7 @@ 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.StringUtils; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -13,7 +14,6 @@ import javax.servlet.http.HttpServletRequest; import java.util.Collection; import java.util.Enumeration; -import java.util.Iterator; import java.util.Map; public class HttpServletHelper { @@ -142,6 +142,10 @@ public static void getJSPMappings(ServletContext servletContext, String dir) { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); for (String path : resourcePaths) { + String entry = StringUtils.removeStart(StringUtils.removeEnd(path, SEPARATOR), StringUtils.SEPARATOR); + if ( StringUtils.equalsAny(entry, "META-INF", "WEB-INF")) { + continue; + } if(path.endsWith(SEPARATOR)) { getJSPMappings(servletContext, 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 5084a7634..69fce5348 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 @@ -5,6 +5,7 @@ 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.schema.StringUtils; import com.newrelic.api.agent.security.utils.logging.LogLevel; import javax.servlet.ServletContext; @@ -36,6 +37,10 @@ public static void getJSPMappings(ServletContext servletContext, String dir) { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); for (String path : resourcePaths) { + String entry = StringUtils.removeStart(StringUtils.removeEnd(path, SEPARATOR), StringUtils.SEPARATOR); + if ( StringUtils.equalsAny(entry, "META-INF", "WEB-INF")) { + continue; + } if(path.endsWith(SEPARATOR)) { getJSPMappings(servletContext, 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 24c53074c..b87171180 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 @@ -5,6 +5,7 @@ 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.StringUtils; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; import jakarta.servlet.ServletContext; @@ -142,6 +143,10 @@ public static void getJSPMappings(ServletContext servletContext, String dir) { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); for (String path : resourcePaths) { + String entry = StringUtils.removeStart(StringUtils.removeEnd(path, SEPARATOR), StringUtils.SEPARATOR); + if ( StringUtils.equalsAny(entry, "META-INF", "WEB-INF")) { + continue; + } if(path.endsWith(SEPARATOR)) { getJSPMappings(servletContext, 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 847d8e440..9f198294e 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 @@ -5,6 +5,7 @@ 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.StringUtils; import com.newrelic.api.agent.security.schema.policy.AgentPolicy; import com.newrelic.api.agent.security.utils.logging.LogLevel; import jakarta.servlet.ServletContext; @@ -142,6 +143,10 @@ public static void getJSPMappings(ServletContext servletContext, String dir) { if(dir.endsWith(SEPARATOR)){ Collection resourcePaths = servletContext.getResourcePaths(dir); for (String path : resourcePaths) { + String entry = StringUtils.removeStart(StringUtils.removeEnd(path, SEPARATOR), StringUtils.SEPARATOR); + if ( StringUtils.equalsAny(entry, "META-INF", "WEB-INF")) { + continue; + } if(path.endsWith(SEPARATOR)) { getJSPMappings(servletContext, path); } From 1851f7046a8df4d24ae2badb4466a8659f11a970 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 28 Aug 2024 16:37:30 +0530 Subject: [PATCH 104/122] add removeStart in StringUtils --- .../agent/security/schema/StringUtils.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) 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 e9f8e89b3..cd35ce8d9 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 @@ -1381,5 +1381,68 @@ public static boolean endsWithAny(final CharSequence sequence, final CharSequenc return false; } + /** + * Removes a char only if it is at the beginning of a source string, + * otherwise returns the source string. + * + *

A {@code null} source string will return {@code null}. + * An empty ("") source string will return the empty string. + * A {@code null} search char will return the source string.

+ * + *
+     * StringUtils.removeStart(null, *)      = null
+     * StringUtils.removeStart("", *)        = ""
+     * StringUtils.removeStart(*, null)      = *
+     * StringUtils.removeStart("/path", '/') = "path"
+     * StringUtils.removeStart("path", '/')  = "path"
+     * StringUtils.removeStart("path", 0)    = "path"
+     * 
+ * + * @param str the source String to search, may be null. + * @param remove the char to search for and remove. + * @return the substring with the char removed if found, + * {@code null} if null String input. + * @since 3.13.0 + */ + public static String removeStart(final String str, final char remove) { + if (isEmpty(str)) { + return str; + } + return str.charAt(0) == remove ? str.substring(1) : str; + } + + /** + * Removes a substring only if it is at the beginning of a source string, + * otherwise returns the source string. + * + *

A {@code null} source string will return {@code null}. + * An empty ("") source string will return the empty string. + * A {@code null} search string will return the source string.

+ * + *
+     * StringUtils.removeStart(null, *)      = null
+     * StringUtils.removeStart("", *)        = ""
+     * StringUtils.removeStart(*, null)      = *
+     * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
+     * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
+     * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
+     * StringUtils.removeStart("abc", "")    = "abc"
+     * 
+ * + * @param str the source String to search, may be null + * @param remove the String to search for and remove, may be null + * @return the substring with the string removed if found, + * {@code null} if null String input + * @since 2.1 + */ + public static String removeStart(final String str, final String remove) { + if (isEmpty(str) || isEmpty(remove)) { + return str; + } + if (str.startsWith(remove)) { + return str.substring(remove.length()); + } + return str; + } } From cfd9a05968d7bc3345135f08649a47e19a6797a7 Mon Sep 17 00:00:00 2001 From: idawda Date: Wed, 28 Aug 2024 19:20:16 +0530 Subject: [PATCH 105/122] NR-306872: Add test-identifier, process start time to websocket headers for CI/CD Support --- .../java/com/newrelic/agent/security/AgentConfig.java | 8 ++++++++ .../agent/security/intcodeagent/websocket/WSClient.java | 5 +++++ .../com/newrelic/agent/security/util/IUtilConstants.java | 1 + 3 files changed, 14 insertions(+) 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 84bda35e3..3625f5861 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 @@ -50,6 +50,8 @@ public class AgentConfig { private Map noticeErrorCustomParams = new HashMap<>(); + private String iastTestIdentifier; + private AgentConfig(){ } @@ -68,6 +70,8 @@ public void instantiate(){ logger = FileLoggerThreadPool.getInstance(); // Set required LogLevel logLevel = applyRequiredLogLevel(); + + iastTestIdentifier = NewRelic.getAgent().getConfig().getValue(IUtilConstants.IAST_TEST_IDENTIFIER); } private static final class InstanceHolder { @@ -224,4 +228,8 @@ public void setNRSecurityEnabled(boolean NRSecurityEnabled) { public String getSecurityHome() { return NR_CSEC_HOME; } + + public String getIastTestIdentifier() { + return iastTestIdentifier; + } } 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 338fb464d..bdf9e8b22 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 @@ -30,6 +30,7 @@ import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.management.ManagementFactory; import java.net.*; import java.nio.file.Files; import java.nio.file.Paths; @@ -152,6 +153,10 @@ private WSClient() throws URISyntaxException { this.addHeader("NR-CSEC-JSON-VERSION", AgentInfo.getInstance().getBuildInfo().getJsonVersion()); this.addHeader("NR-ACCOUNT-ID", AgentConfig.getInstance().getConfig().getCustomerInfo().getAccountId()); this.addHeader("NR-CSEC-IAST-DATA-TRANSFER-MODE", "PULL"); + if (AgentConfig.getInstance().getIastTestIdentifier() != null) { + this.addHeader("NR-CSEC-IAST-TEST-IDENTIFIER", AgentConfig.getInstance().getIastTestIdentifier()); + this.addHeader("NR-CSEC-PROCESS-START-TIME", String.valueOf(ManagementFactory.getRuntimeMXBean().getStartTime())); + } Proxy proxy = proxyManager(); if(proxy != null) { this.setProxy(proxy); 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 ebe2c6f28..0045c853d 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 @@ -24,6 +24,7 @@ public interface IUtilConstants { String NR_SECURITY_ENABLED = "security.enabled"; String NR_SECURITY_HOME_APP = "security.is_home_app"; + String IAST_TEST_IDENTIFIER = "security.iast_test_identifier"; String NR_SECURITY_CA_BUNDLE_PATH = "ca_bundle_path"; String NR_CSEC_DEBUG_LOGFILE_SIZE = "NR_CSEC_DEBUG_LOGFILE_SIZE"; From 1a98cb0dd151cab0b5362f35f7cc7fe820b038bb Mon Sep 17 00:00:00 2001 From: idawda Date: Thu, 29 Aug 2024 10:18:05 +0530 Subject: [PATCH 106/122] roundup the value for currentFetchThreshold --- .../httpclient/IASTDataTransferRequestProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java index 511ca2282..a1641ac4b 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java @@ -77,7 +77,7 @@ private void task() { return; } - int currentFetchThreshold = currentFetchThresholdPerMin/12; + int currentFetchThreshold = Math.round((float) currentFetchThresholdPerMin/12); if (currentFetchThreshold <= 0){ return; } From 794311744c98853695919f0e02048c11c4e48a66 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 30 Aug 2024 10:36:02 +0530 Subject: [PATCH 107/122] remove dependency of start-time header on test-identifier header --- .../agent/security/intcodeagent/websocket/WSClient.java | 2 +- 1 file changed, 1 insertion(+), 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 bdf9e8b22..da32c5c62 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 @@ -155,8 +155,8 @@ private WSClient() throws URISyntaxException { this.addHeader("NR-CSEC-IAST-DATA-TRANSFER-MODE", "PULL"); if (AgentConfig.getInstance().getIastTestIdentifier() != null) { this.addHeader("NR-CSEC-IAST-TEST-IDENTIFIER", AgentConfig.getInstance().getIastTestIdentifier()); - this.addHeader("NR-CSEC-PROCESS-START-TIME", String.valueOf(ManagementFactory.getRuntimeMXBean().getStartTime())); } + this.addHeader("NR-CSEC-PROCESS-START-TIME", String.valueOf(ManagementFactory.getRuntimeMXBean().getStartTime())); Proxy proxy = proxyManager(); if(proxy != null) { this.setProxy(proxy); From 3ba7bdc5d14a0ddeb09cd4534b4b22cc49281629 Mon Sep 17 00:00:00 2001 From: idawda Date: Fri, 30 Aug 2024 12:51:22 +0530 Subject: [PATCH 108/122] Correct User Entity detection for gRPC --- .../main/java/io/grpc/ServerCallListener_Instrumentation.java | 3 +++ .../main/java/io/grpc/ServerCallListener_Instrumentation.java | 3 +++ .../main/java/io/grpc/ServerCallListener_Instrumentation.java | 3 +++ .../src/main/java/com/newrelic/api/agent/security/Agent.java | 1 + 4 files changed, 10 insertions(+) diff --git a/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java b/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java index 299f2885e..677671b37 100644 --- a/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java +++ b/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java @@ -7,6 +7,8 @@ import com.newrelic.api.agent.Token; import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.Framework; import com.newrelic.api.agent.security.schema.SecurityMetaData; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.NewField; @@ -32,6 +34,7 @@ public void onMessage(ReqT message) { if (isLockAcquired) { GrpcUtils.preProcessSecurityHook(message, GrpcUtils.Type.REQUEST, descriptorForType.getFullName()); } + ServletHelper.registerUserLevelCode(Framework.GRPC.name()); try { Weaver.callOriginal(); } finally { diff --git a/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java b/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java index 5347df9c1..b1b4b49b0 100644 --- a/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java +++ b/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java @@ -7,6 +7,8 @@ import com.newrelic.api.agent.Token; import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.Framework; import com.newrelic.api.agent.security.schema.SecurityMetaData; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.NewField; @@ -32,6 +34,7 @@ public void onMessage(ReqT message) { if (isLockAcquired) { GrpcUtils.preProcessSecurityHook(message, GrpcUtils.Type.REQUEST, descriptorForType.getFullName()); } + ServletHelper.registerUserLevelCode(Framework.GRPC.name()); try { Weaver.callOriginal(); } finally { diff --git a/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java b/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java index a26fb4170..406e6cca8 100644 --- a/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java +++ b/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/ServerCallListener_Instrumentation.java @@ -7,6 +7,8 @@ import com.newrelic.api.agent.Token; import com.newrelic.api.agent.Trace; import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; +import com.newrelic.api.agent.security.schema.Framework; import com.newrelic.api.agent.security.schema.SecurityMetaData; import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.NewField; @@ -32,6 +34,7 @@ public void onMessage(ReqT message) { if (isLockAcquired) { GrpcUtils.preProcessSecurityHook(message, GrpcUtils.Type.REQUEST, descriptorForType.getFullName()); } + ServletHelper.registerUserLevelCode(Framework.GRPC.name()); try { Weaver.callOriginal(); } finally { 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 f0241ac02..dc65e8bd6 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 @@ -519,6 +519,7 @@ private UserClassEntity setUserClassEntity(AbstractOperation operation, Security } switch (framework){ case "vertx-web": + case "GRPC": if(i-1 >= 0) { userClassEntity = setUserClassEntityForVertx(operation, userStackTraceElement, userClassEntity, securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(), i); if(userClassEntity.getUserClassElement() != null){ From 721ed8e12c5777f3ddb8792e6619dc9cf8516acf Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 2 Sep 2024 13:32:46 +0530 Subject: [PATCH 109/122] agent version bump 1.4.2 json version bump to 1.2.7 add procStartTime & scanStartTime to HealthCheck --- gradle.properties | 4 ++-- .../IASTDataTransferRequestProcessor.java | 10 ++++++++ .../models/javaagent/JAHealthCheck.java | 24 +++++++++++++++++++ .../agent/security/util/IUtilConstants.java | 2 +- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 9cf70671d..79ca433d4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # The agent version. -agentVersion=1.4.1 -jsonVersion=1.2.6 +agentVersion=1.4.2 +jsonVersion=1.2.7 # Updated exposed NR APM API version. nrAPIVersion=8.12.0 diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java index a1641ac4b..5c253beec 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java @@ -49,6 +49,8 @@ public class IASTDataTransferRequestProcessor { private int currentFetchThresholdPerMin = 3600; + private long scanStartEpochMilli = 0; + private void task() { IASTDataTransferRequest request = null; try { @@ -67,6 +69,10 @@ private void task() { } } long currentTimestamp = Instant.now().toEpochMilli(); + if(scanStartEpochMilli <= 0){ + AgentInfo.getInstance().getJaHealthCheck().setScanStartTime(currentTimestamp); + scanStartEpochMilli = currentTimestamp; + } // Sleep if under cooldown long cooldownSleepTime = cooldownTillTimestamp.get() - currentTimestamp; if(cooldownSleepTime > 0) { @@ -197,4 +203,8 @@ public void setCooldownTillTimestamp(long timestamp) { public void setLastFuzzCCTimestamp(long timestamp) { lastFuzzCCTimestamp.set(timestamp); } + + public long getScanStartEpochMilli() { + return scanStartEpochMilli; + } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java index 7eb7f024b..57fb764ae 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java @@ -5,6 +5,7 @@ import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; +import java.lang.management.ManagementFactory; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -18,6 +19,10 @@ public class JAHealthCheck extends AgentBasicInfo { // private Set protectedDB; + private long procStartTime; + + private long scanStartTime; + private AtomicInteger invokedHookCount; private IdentifierEnvs kind; @@ -45,6 +50,7 @@ public JAHealthCheck(String applicationUUID) { this.serviceStatus = new HashMap<>(); this.eventStats = new EventStats(); this.setKind(AgentInfo.getInstance().getApplicationInfo().getIdentifier().getKind()); + this.procStartTime = ManagementFactory.getRuntimeMXBean().getStartTime(); logger.log(LogLevel.INFO, String.format(HC_CREATED, JsonConverter.toJSON(this)), JAHealthCheck.class.getName()); } @@ -59,6 +65,8 @@ public JAHealthCheck(JAHealthCheck jaHealthCheck) { this.schedulerRuns = new SchedulerRuns(jaHealthCheck.schedulerRuns); this.invokedHookCount = new AtomicInteger(jaHealthCheck.invokedHookCount.get()); this.webSocketConnectionStats = new WebSocketConnectionStats(jaHealthCheck.webSocketConnectionStats); + this.procStartTime = jaHealthCheck.getProcStartTime(); + this.scanStartTime = jaHealthCheck.getScanStartTime(); logger.log(LogLevel.INFO, String.format(HC_CREATED, JsonConverter.toJSON(this)), JAHealthCheck.class.getName()); } @@ -133,6 +141,22 @@ public void setSchedulerRuns(SchedulerRuns schedulerRuns) { this.schedulerRuns = schedulerRuns; } + public long getProcStartTime() { + return procStartTime; + } + + public void setProcStartTime(long procStartTime) { + this.procStartTime = procStartTime; + } + + public long getScanStartTime() { + return scanStartTime; + } + + public void setScanStartTime(long scanStartTime) { + this.scanStartTime = scanStartTime; + } + public void reset(){ this.setInvokedHookCount(0); this.stats.clear(); 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 0589266cd..d04d53cc7 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 @@ -12,7 +12,7 @@ public interface IUtilConstants { String SCAN_TIME_SCHEDULE = "security.scan_schedule.schedule"; String SCAN_TIME_DURATION = "security.scan_schedule.duration"; String SCAN_TIME_COLLECT_SAMPLES = "security.scan_schedule.always_sample_traces"; - String SCAN_REQUEST_RATE_LIMIT = "security.scan_request_rate_limit"; + String SCAN_REQUEST_RATE_LIMIT = "security.scan_controllers.iast_scan_request_rate_limit"; String SKIP_IAST_SCAN = "security.exclude_from_iast_scan"; String SKIP_IAST_SCAN_API = SKIP_IAST_SCAN + ".api"; From 339ee15eac844e88521005ed7d45078f804ed9cf Mon Sep 17 00:00:00 2001 From: idawda Date: Mon, 2 Sep 2024 16:42:27 +0530 Subject: [PATCH 110/122] Route detection support for gRPC --- .../grpc/internal/ServerImpl_Instrumentation.java | 13 +++++++++++++ .../grpc/internal/ServerImpl_Instrumentation.java | 13 +++++++++++++ .../grpc/internal/ServerImpl_Instrumentation.java | 13 +++++++++++++ 3 files changed, 39 insertions(+) diff --git a/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java b/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java index e1bc40df9..5b543db04 100644 --- a/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java +++ b/instrumentation-security/grpc-1.22.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java @@ -8,8 +8,13 @@ package io.grpc.internal; import com.newrelic.agent.security.instrumentation.grpc1220.GrpcServerUtils; +import com.newrelic.agent.security.instrumentation.grpc1220.GrpcUtils; import com.newrelic.agent.security.instrumentation.grpc1220.processor.MonitorGrpcRequestQueueThread; import com.newrelic.api.agent.NewRelic; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.Framework; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import io.grpc.Context; @@ -29,6 +34,14 @@ private ServerStreamListener startCall(ServerStream_Instrumentatio stream.tokenForCsec = NewRelic.getAgent().getTransaction().getToken(); MonitorGrpcRequestQueueThread.submitNewTask(); boolean isLockAcquired = GrpcServerUtils.acquireLockIfPossible(); + try { + if (NewRelicSecurity.isHookProcessingActive()){ + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(methodDef.getMethodDescriptor().getFullMethodName()); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.GRPC); + } + } catch (Exception e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, GrpcUtils.GRPC_1_22_0, e.getMessage()), e, this.getClass().getName()); + } if (isLockAcquired) { GrpcServerUtils.preprocessSecurityHook(stream, methodDef, headers, this.getClass().getName()); } diff --git a/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java b/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java index b4228c8d3..a65812d3a 100644 --- a/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java +++ b/instrumentation-security/grpc-1.4.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java @@ -8,8 +8,13 @@ package io.grpc.internal; import com.newrelic.agent.security.instrumentation.grpc140.GrpcServerUtils; +import com.newrelic.agent.security.instrumentation.grpc140.GrpcUtils; import com.newrelic.agent.security.instrumentation.grpc140.processor.MonitorGrpcRequestQueueThread; import com.newrelic.api.agent.NewRelic; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.Framework; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; import io.grpc.Context; @@ -28,6 +33,14 @@ private ServerStreamListener startCall(ServerStream_Instrumentatio stream.tokenForCsec = NewRelic.getAgent().getTransaction().getToken(); MonitorGrpcRequestQueueThread.submitNewTask(); boolean isLockAcquired = GrpcServerUtils.acquireLockIfPossible(); + try { + if (NewRelicSecurity.isHookProcessingActive()){ + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(methodDef.getMethodDescriptor().getFullMethodName()); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.GRPC); + } + } catch (Exception e){ + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, GrpcUtils.GRPC_1_4_0, e.getMessage()), e, this.getClass().getName()); + } if (isLockAcquired) { GrpcServerUtils.preprocessSecurityHook(stream, methodDef, headers, this.getClass().getName()); } diff --git a/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java b/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java index f3e5ffaf1..a3d94e077 100644 --- a/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java +++ b/instrumentation-security/grpc-1.40.0/src/main/java/io/grpc/internal/ServerImpl_Instrumentation.java @@ -1,8 +1,13 @@ package io.grpc.internal; import com.newrelic.agent.security.instrumentation.grpc1400.GrpcServerUtils; +import com.newrelic.agent.security.instrumentation.grpc1400.GrpcUtils; import com.newrelic.agent.security.instrumentation.grpc1400.processor.MonitorGrpcRequestQueueThread; import com.newrelic.api.agent.NewRelic; +import com.newrelic.api.agent.security.NewRelicSecurity; +import com.newrelic.api.agent.security.instrumentation.helpers.GenericHelper; +import com.newrelic.api.agent.security.schema.Framework; +import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.api.agent.weaver.NewField; import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; @@ -28,6 +33,14 @@ private void streamCreatedInternal(final ServerStream stream, final String metho private ServerMethodDefinition wrapMethod(ServerStream_Instrumentation stream, ServerMethodDefinition methodDef, StatsTraceContext statsTraceCtx) { stream.tokenForCsec = NewRelic.getAgent().getTransaction().getToken(); boolean isLockAcquired = GrpcServerUtils.acquireLockIfPossible(); + try { + if (NewRelicSecurity.isHookProcessingActive()){ + NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().setRoute(methodDef.getMethodDescriptor().getFullMethodName()); + NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFramework(Framework.GRPC); + } + } catch (Exception e) { + NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_WHILE_GETTING_ROUTE_FOR_INCOMING_REQUEST, GrpcUtils.GRPC_1_40_0, e.getMessage()), e, this.getClass().getName()); + } if (isLockAcquired) { GrpcServerUtils.preprocessSecurityHook(stream, methodDef, headers, this.getClass().getName()); } From 5ffd62ded99a3dac571f3c47b185bfb32c02c5ae Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Mon, 2 Sep 2024 18:15:04 +0530 Subject: [PATCH 111/122] set scan start time on every NR IAST trigger --- .../src/main/java/com/newrelic/api/agent/security/Agent.java | 2 +- 1 file changed, 1 insertion(+), 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 3aa31e43d..444b9bb0b 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 @@ -279,7 +279,7 @@ private void startSecurityServices() { } else { IASTDataTransferRequestProcessor.getInstance().stopDataRequestSchedule(true); } - + AgentInfo.getInstance().getJaHealthCheck().setScanStartTime(IASTDataTransferRequestProcessor.getInstance().getScanStartEpochMilli()); } @Override From 57be1b64184ab2c34a2280867820100492a0d123 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 3 Sep 2024 12:47:52 +0530 Subject: [PATCH 112/122] New Requirements Enhancing Health Checks with State Information --- .../IASTDataTransferRequestProcessor.java | 14 ++--- .../ControlCommandProcessor.java | 4 ++ .../ControlCommandProcessorThreadPool.java | 9 +++ .../models/javaagent/JAHealthCheck.java | 63 +++++++++++++++++-- .../newrelic/api/agent/security/Agent.java | 9 ++- 5 files changed, 86 insertions(+), 13 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java index 5c253beec..b6ae89e8d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java @@ -3,7 +3,6 @@ import com.newrelic.agent.security.AgentConfig; import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.instrumentator.utils.INRSettingsKey; -import com.newrelic.agent.security.intcodeagent.exceptions.RestrictionModeException; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.util.IUtilConstants; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -49,7 +48,7 @@ public class IASTDataTransferRequestProcessor { private int currentFetchThresholdPerMin = 3600; - private long scanStartEpochMilli = 0; + private long controlCommandRequestedAtEpochMilli = 0; private void task() { IASTDataTransferRequest request = null; @@ -69,9 +68,10 @@ private void task() { } } long currentTimestamp = Instant.now().toEpochMilli(); - if(scanStartEpochMilli <= 0){ - AgentInfo.getInstance().getJaHealthCheck().setScanStartTime(currentTimestamp); - scanStartEpochMilli = currentTimestamp; + if(controlCommandRequestedAtEpochMilli <= 0){ + AgentInfo.getInstance().getJaHealthCheck().setControlCommandRequestedAt(currentTimestamp); + controlCommandRequestedAtEpochMilli = currentTimestamp; + AgentInfo.getInstance().getJaHealthCheck().setScanActive(true); } // Sleep if under cooldown long cooldownSleepTime = cooldownTillTimestamp.get() - currentTimestamp; @@ -204,7 +204,7 @@ public void setLastFuzzCCTimestamp(long timestamp) { lastFuzzCCTimestamp.set(timestamp); } - public long getScanStartEpochMilli() { - return scanStartEpochMilli; + public long getControlCommandRequestedAtEpochMilli() { + return controlCommandRequestedAtEpochMilli; } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java index 6679724f0..033913645 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java @@ -177,6 +177,10 @@ public void run() { iastReplayRequestMsgReceiveTime = Instant.now(); IASTDataTransferRequestProcessor.getInstance().setLastFuzzCCTimestamp(Instant.now().toEpochMilli()); RestRequestProcessor.processControlCommand(controlCommand); + if(ControlCommandProcessorThreadPool.getInstance().getScanStartTime() <= 0) { + ControlCommandProcessorThreadPool.getInstance().setScanStartTime(Instant.now().toEpochMilli()); + AgentInfo.getInstance().getJaHealthCheck().setScanStartTime(ControlCommandProcessorThreadPool.getInstance().getScanStartTime()); + } break; case IntCodeControlCommand.STARTUP_WELCOME_MSG: diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java index badd1c22a..0b432f3d9 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessorThreadPool.java @@ -27,6 +27,8 @@ public class ControlCommandProcessorThreadPool { private final boolean allowCoreThreadTimeOut = false; private static Object mutex = new Object(); + private long scanStartTime = 0; + public ThreadPoolExecutor getExecutor() { return executor; } @@ -157,4 +159,11 @@ public void shutDownThreadPoolExecutor() { } } + public long getScanStartTime() { + return scanStartTime; + } + + public void setScanStartTime(long scanStartTime) { + this.scanStartTime = scanStartTime; + } } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java index 57fb764ae..235b63e6a 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java @@ -1,11 +1,13 @@ package com.newrelic.agent.security.intcodeagent.models.javaagent; +import com.newrelic.agent.security.AgentConfig; import com.newrelic.agent.security.AgentInfo; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter; import java.lang.management.ManagementFactory; +import java.time.Instant; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -15,14 +17,20 @@ public class JAHealthCheck extends AgentBasicInfo { private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); private static final String HC_CREATED = "Created Health Check: %s"; -// private String protectedServer; - -// private Set protectedDB; - private long procStartTime; + private long controlCommandRequestedAt; + private long scanStartTime; + private long trafficStartedAt; + + private final long csecActivationTime; + + private final long iastActivationTime; + + private Boolean scanActive = false; + private AtomicInteger invokedHookCount; private IdentifierEnvs kind; @@ -51,6 +59,16 @@ public JAHealthCheck(String applicationUUID) { this.eventStats = new EventStats(); this.setKind(AgentInfo.getInstance().getApplicationInfo().getIdentifier().getKind()); this.procStartTime = ManagementFactory.getRuntimeMXBean().getStartTime(); + if(AgentConfig.getInstance().getAgentMode().getScanSchedule().getNextScanTime() != null) { + this.csecActivationTime = AgentConfig.getInstance().getAgentMode().getScanSchedule().getNextScanTime().getTime(); + } else { + this.csecActivationTime = Instant.now().toEpochMilli(); + } + if(AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime() != null) { + this.iastActivationTime = AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime().getTime(); + } else { + this.iastActivationTime = Instant.now().toEpochMilli(); + } logger.log(LogLevel.INFO, String.format(HC_CREATED, JsonConverter.toJSON(this)), JAHealthCheck.class.getName()); } @@ -66,7 +84,12 @@ public JAHealthCheck(JAHealthCheck jaHealthCheck) { this.invokedHookCount = new AtomicInteger(jaHealthCheck.invokedHookCount.get()); this.webSocketConnectionStats = new WebSocketConnectionStats(jaHealthCheck.webSocketConnectionStats); this.procStartTime = jaHealthCheck.getProcStartTime(); + this.controlCommandRequestedAt = jaHealthCheck.getControlCommandRequestedAt(); this.scanStartTime = jaHealthCheck.getScanStartTime(); + this.trafficStartedAt = jaHealthCheck.getTrafficStartedAt(); + this.csecActivationTime = jaHealthCheck.getCsecActivationTime(); + this.iastActivationTime = jaHealthCheck.getIastActivationTime(); + this.scanActive = jaHealthCheck.getScanActive(); logger.log(LogLevel.INFO, String.format(HC_CREATED, JsonConverter.toJSON(this)), JAHealthCheck.class.getName()); } @@ -149,6 +172,14 @@ public void setProcStartTime(long procStartTime) { this.procStartTime = procStartTime; } + public long getControlCommandRequestedAt() { + return controlCommandRequestedAt; + } + + public void setControlCommandRequestedAt(long controlCommandRequestedAt) { + this.controlCommandRequestedAt = controlCommandRequestedAt; + } + public long getScanStartTime() { return scanStartTime; } @@ -157,6 +188,30 @@ public void setScanStartTime(long scanStartTime) { this.scanStartTime = scanStartTime; } + public long getTrafficStartedAt() { + return trafficStartedAt; + } + + public void setTrafficStartedAt(long trafficStartedAt) { + this.trafficStartedAt = trafficStartedAt; + } + + public long getCsecActivationTime() { + return csecActivationTime; + } + + public Boolean getScanActive() { + return scanActive; + } + + public void setScanActive(Boolean scanActive) { + this.scanActive = scanActive; + } + + public long getIastActivationTime() { + return iastActivationTime; + } + public void reset(){ this.setInvokedHookCount(0); this.stats.clear(); 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 444b9bb0b..9ce8a5f02 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 @@ -15,7 +15,6 @@ import com.newrelic.agent.security.intcodeagent.exceptions.RestrictionModeException; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.agent.security.intcodeagent.filelogging.LogFileHelper; -import com.newrelic.agent.security.intcodeagent.models.collectorconfig.AgentMode; import com.newrelic.agent.security.intcodeagent.models.javaagent.*; import com.newrelic.agent.security.intcodeagent.utils.*; import com.newrelic.api.agent.security.instrumentation.helpers.*; @@ -62,6 +61,7 @@ public class Agent implements SecurityAgent { public static final String DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL = "Dropping event as it was generated by agent internal API call : "; private static final AtomicBoolean firstEventProcessed = new AtomicBoolean(false); + private long trafficStartedAt = 0; public static final String ERROR_WHILE_GENERATING_TRACE_ID_FOR_CATEGORY_S = "Error while generating trace id for category : %s"; public static final String SKIPPING_THE_API_S_AS_IT_IS_PART_OF_THE_SKIP_SCAN_LIST = "Skipping the API %s as it is part of the skip scan list"; public static final String INVALID_CRON_EXPRESSION_PROVIDED_FOR_IAST_RESTRICTED_MODE = "Invalid cron expression provided for IAST Mode"; @@ -261,6 +261,7 @@ private void startSecurityServices() { ); WSReconnectionST.getInstance().submitNewTaskSchedule(0); EventSendPool.getInstance(); + ControlCommandProcessorThreadPool.getInstance(); logger.logInit( LogLevel.INFO, String.format(STARTED_MODULE_LOG, AgentServices.EventWritePool.name()), @@ -279,7 +280,8 @@ private void startSecurityServices() { } else { IASTDataTransferRequestProcessor.getInstance().stopDataRequestSchedule(true); } - AgentInfo.getInstance().getJaHealthCheck().setScanStartTime(IASTDataTransferRequestProcessor.getInstance().getScanStartEpochMilli()); + AgentInfo.getInstance().getJaHealthCheck().setControlCommandRequestedAt(IASTDataTransferRequestProcessor.getInstance().getControlCommandRequestedAtEpochMilli()); + AgentInfo.getInstance().getJaHealthCheck().setScanStartTime(ControlCommandProcessorThreadPool.getInstance().getScanStartTime()); } @Override @@ -344,6 +346,7 @@ private void deactivateSecurityServices(){ */ // InstrumentationUtils.shutdownLogic(); IASTDataTransferRequestProcessor.getInstance().stopDataRequestSchedule(true); + info.getJaHealthCheck().setScanActive(false); if(!config.getAgentMode().getScanSchedule().isCollectSamples()) { AgentInfo.getInstance().setAgentActive(false); HealthCheckScheduleThread.getInstance().cancelTask(true); @@ -468,6 +471,8 @@ public void registerOperation(AbstractOperation operation) { String.format(EVENT_ZERO_PROCESSED, securityMetaData.getRequest()), this.getClass().getName()); firstEventProcessed.set(true); + trafficStartedAt = Instant.now().toEpochMilli(); + AgentInfo.getInstance().getJaHealthCheck().setTrafficStartedAt(trafficStartedAt); } } } From 30801b7bf3a4370fed04c0774d27ea6f8c6dbede Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Tue, 3 Sep 2024 17:55:30 +0530 Subject: [PATCH 113/122] rename fields according to NR-308822 --- .../IASTDataTransferRequestProcessor.java | 2 +- .../models/javaagent/JAHealthCheck.java | 36 +++++++++---------- .../newrelic/api/agent/security/Agent.java | 4 +-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java index b6ae89e8d..d2221a522 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java @@ -69,7 +69,7 @@ private void task() { } long currentTimestamp = Instant.now().toEpochMilli(); if(controlCommandRequestedAtEpochMilli <= 0){ - AgentInfo.getInstance().getJaHealthCheck().setControlCommandRequestedAt(currentTimestamp); + AgentInfo.getInstance().getJaHealthCheck().setControlCommandRequestedTime(currentTimestamp); controlCommandRequestedAtEpochMilli = currentTimestamp; AgentInfo.getInstance().getJaHealthCheck().setScanActive(true); } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java index 235b63e6a..cd926be52 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/models/javaagent/JAHealthCheck.java @@ -19,15 +19,15 @@ public class JAHealthCheck extends AgentBasicInfo { private long procStartTime; - private long controlCommandRequestedAt; + private long controlCommandRequestedTime; private long scanStartTime; - private long trafficStartedAt; + private long trafficStartedTime; private final long csecActivationTime; - private final long iastActivationTime; + private final long iastDataRequestTime; private Boolean scanActive = false; @@ -65,9 +65,9 @@ public JAHealthCheck(String applicationUUID) { this.csecActivationTime = Instant.now().toEpochMilli(); } if(AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime() != null) { - this.iastActivationTime = AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime().getTime(); + this.iastDataRequestTime = AgentConfig.getInstance().getAgentMode().getScanSchedule().getDataCollectionTime().getTime(); } else { - this.iastActivationTime = Instant.now().toEpochMilli(); + this.iastDataRequestTime = Instant.now().toEpochMilli(); } logger.log(LogLevel.INFO, String.format(HC_CREATED, JsonConverter.toJSON(this)), JAHealthCheck.class.getName()); } @@ -84,11 +84,11 @@ public JAHealthCheck(JAHealthCheck jaHealthCheck) { this.invokedHookCount = new AtomicInteger(jaHealthCheck.invokedHookCount.get()); this.webSocketConnectionStats = new WebSocketConnectionStats(jaHealthCheck.webSocketConnectionStats); this.procStartTime = jaHealthCheck.getProcStartTime(); - this.controlCommandRequestedAt = jaHealthCheck.getControlCommandRequestedAt(); + this.controlCommandRequestedTime = jaHealthCheck.getControlCommandRequestedTime(); this.scanStartTime = jaHealthCheck.getScanStartTime(); - this.trafficStartedAt = jaHealthCheck.getTrafficStartedAt(); + this.trafficStartedTime = jaHealthCheck.getTrafficStartedTime(); this.csecActivationTime = jaHealthCheck.getCsecActivationTime(); - this.iastActivationTime = jaHealthCheck.getIastActivationTime(); + this.iastDataRequestTime = jaHealthCheck.getIastDataRequestTime(); this.scanActive = jaHealthCheck.getScanActive(); logger.log(LogLevel.INFO, String.format(HC_CREATED, JsonConverter.toJSON(this)), JAHealthCheck.class.getName()); } @@ -172,12 +172,12 @@ public void setProcStartTime(long procStartTime) { this.procStartTime = procStartTime; } - public long getControlCommandRequestedAt() { - return controlCommandRequestedAt; + public long getControlCommandRequestedTime() { + return controlCommandRequestedTime; } - public void setControlCommandRequestedAt(long controlCommandRequestedAt) { - this.controlCommandRequestedAt = controlCommandRequestedAt; + public void setControlCommandRequestedTime(long controlCommandRequestedTime) { + this.controlCommandRequestedTime = controlCommandRequestedTime; } public long getScanStartTime() { @@ -188,12 +188,12 @@ public void setScanStartTime(long scanStartTime) { this.scanStartTime = scanStartTime; } - public long getTrafficStartedAt() { - return trafficStartedAt; + public long getTrafficStartedTime() { + return trafficStartedTime; } - public void setTrafficStartedAt(long trafficStartedAt) { - this.trafficStartedAt = trafficStartedAt; + public void setTrafficStartedTime(long trafficStartedTime) { + this.trafficStartedTime = trafficStartedTime; } public long getCsecActivationTime() { @@ -208,8 +208,8 @@ public void setScanActive(Boolean scanActive) { this.scanActive = scanActive; } - public long getIastActivationTime() { - return iastActivationTime; + public long getIastDataRequestTime() { + return iastDataRequestTime; } public void reset(){ 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 9ce8a5f02..398e61f30 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 @@ -280,7 +280,7 @@ private void startSecurityServices() { } else { IASTDataTransferRequestProcessor.getInstance().stopDataRequestSchedule(true); } - AgentInfo.getInstance().getJaHealthCheck().setControlCommandRequestedAt(IASTDataTransferRequestProcessor.getInstance().getControlCommandRequestedAtEpochMilli()); + AgentInfo.getInstance().getJaHealthCheck().setControlCommandRequestedTime(IASTDataTransferRequestProcessor.getInstance().getControlCommandRequestedAtEpochMilli()); AgentInfo.getInstance().getJaHealthCheck().setScanStartTime(ControlCommandProcessorThreadPool.getInstance().getScanStartTime()); } @@ -472,7 +472,7 @@ public void registerOperation(AbstractOperation operation) { this.getClass().getName()); firstEventProcessed.set(true); trafficStartedAt = Instant.now().toEpochMilli(); - AgentInfo.getInstance().getJaHealthCheck().setTrafficStartedAt(trafficStartedAt); + AgentInfo.getInstance().getJaHealthCheck().setTrafficStartedTime(trafficStartedAt); } } } From d1f12e530fcfa50323a994dfd688a8fbbeec7f20 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 6 Sep 2024 17:38:02 +0530 Subject: [PATCH 114/122] Cleanup IAST data collection locks --- .../processor/GrpcRequestThreadPool.java | 6 ------ .../processor/GrpcRequestThreadPool.java | 6 ------ .../processor/GrpcRequestThreadPool.java | 6 ------ .../IASTDataTransferRequestProcessor.java | 19 +++++++++-------- .../httpclient/RestRequestProcessor.java | 14 ++++++------- .../httpclient/RestRequestThreadPool.java | 6 ------ .../ControlCommandProcessor.java | 21 +------------------ .../intcodeagent/logging/IAgentConstants.java | 1 + .../intcodeagent/websocket/EventSendPool.java | 6 ------ .../intcodeagent/websocket/EventSender.java | 7 ------- .../GrpcClientRequestReplayHelper.java | 5 ----- 11 files changed, 19 insertions(+), 78 deletions(-) diff --git a/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/processor/GrpcRequestThreadPool.java b/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/processor/GrpcRequestThreadPool.java index 178defe2c..b20081e13 100644 --- a/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/processor/GrpcRequestThreadPool.java +++ b/instrumentation-security/grpc-1.22.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1220/processor/GrpcRequestThreadPool.java @@ -35,8 +35,6 @@ public class GrpcRequestThreadPool { private final boolean allowCoreThreadTimeOut = false; private static final Object mutex = new Object(); - private static final AtomicBoolean isWaiting = new AtomicBoolean(false); - private GrpcRequestThreadPool() { LinkedBlockingQueue processQueue; // load the settings @@ -136,10 +134,6 @@ public BlockingQueue getQueue() { return this.executor.getQueue(); } - public AtomicBoolean isWaiting() { - return isWaiting; - } - public ThreadPoolExecutor getExecutor() { return executor; } diff --git a/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/processor/GrpcRequestThreadPool.java b/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/processor/GrpcRequestThreadPool.java index a2e8fceef..32e8eec98 100644 --- a/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/processor/GrpcRequestThreadPool.java +++ b/instrumentation-security/grpc-1.4.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc140/processor/GrpcRequestThreadPool.java @@ -35,8 +35,6 @@ public class GrpcRequestThreadPool { private final boolean allowCoreThreadTimeOut = false; private static final Object mutex = new Object(); - private static final AtomicBoolean isWaiting = new AtomicBoolean(false); - private GrpcRequestThreadPool() { LinkedBlockingQueue processQueue; // load the settings @@ -136,10 +134,6 @@ public BlockingQueue getQueue() { return this.executor.getQueue(); } - public AtomicBoolean isWaiting() { - return isWaiting; - } - public ThreadPoolExecutor getExecutor() { return executor; } diff --git a/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/processor/GrpcRequestThreadPool.java b/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/processor/GrpcRequestThreadPool.java index 1e23a656b..de3b95a28 100644 --- a/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/processor/GrpcRequestThreadPool.java +++ b/instrumentation-security/grpc-1.40.0/src/main/java/com/newrelic/agent/security/instrumentation/grpc1400/processor/GrpcRequestThreadPool.java @@ -33,8 +33,6 @@ public class GrpcRequestThreadPool { private final boolean allowCoreThreadTimeOut = false; private static final Object mutex = new Object(); - private static final AtomicBoolean isWaiting = new AtomicBoolean(false); - private GrpcRequestThreadPool() { LinkedBlockingQueue processQueue; // load the settings @@ -134,10 +132,6 @@ public BlockingQueue getQueue() { return this.executor.getQueue(); } - public AtomicBoolean isWaiting() { - return isWaiting; - } - public ThreadPoolExecutor getExecutor() { return executor; } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java index d2221a522..4832c2412 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/IASTDataTransferRequestProcessor.java @@ -54,19 +54,20 @@ private void task() { IASTDataTransferRequest request = null; try { if(!AgentUsageMetric.isIASTRequestProcessingActive()){ + logger.log(LogLevel.FINER, "IAST request processing deactivated for the moment.", IASTDataTransferRequestProcessor.class.getName()); return; } - if (WSUtils.getInstance().isReconnecting() || - !WSClient.getInstance().isOpen()) { - synchronized (WSUtils.getInstance()) { - RestRequestThreadPool.getInstance().isWaiting().set(true); - GrpcClientRequestReplayHelper.getInstance().isWaiting().set(true); - WSUtils.getInstance().wait(); - RestRequestThreadPool.getInstance().isWaiting().set(false); - GrpcClientRequestReplayHelper.getInstance().isWaiting().set(false); - } + if (!WSClient.getInstance().isOpen()) { + logger.log(LogLevel.FINER, "IAST request processing deactivated due to websocket connection status.", IASTDataTransferRequestProcessor.class.getName()); + return; + } + + if(WSUtils.getInstance().isReconnecting()) { + logger.log(LogLevel.FINER, "IAST request processing deactivated due to SE requested for reconnection..", IASTDataTransferRequestProcessor.class.getName()); + return; } + long currentTimestamp = Instant.now().toEpochMilli(); if(controlCommandRequestedAtEpochMilli <= 0){ AgentInfo.getInstance().getJaHealthCheck().setControlCommandRequestedTime(currentTimestamp); 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 1baa1d69a..618d33a0f 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 @@ -41,6 +41,9 @@ 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 static final String IAST_REQUEST_HAS_NO_ARGUMENTS = "IAST request has no arguments : %s"; + public static final String AGENT_IS_NOT_ACTIVE = "Agent is not active"; + public static final String WS_RECONNECTING = "Websocket reconnecting failing for control command id: %s"; private IntCodeControlCommand controlCommand; private int repeatCount; @@ -61,22 +64,19 @@ public RestRequestProcessor(IntCodeControlCommand controlCommand, int repeatCoun @Override public Boolean call() throws InterruptedException { if (controlCommand.getArguments().size() < 2 ) { + logger.log(LogLevel.FINER, String.format(IAST_REQUEST_HAS_NO_ARGUMENTS, controlCommand.getId()), RestRequestProcessor.class.getSimpleName()); return true; } if( !AgentInfo.getInstance().isAgentActive()) { + logger.log(LogLevel.FINER, AGENT_IS_NOT_ACTIVE, RestRequestProcessor.class.getSimpleName()); return false; } FuzzRequestBean httpRequest = null; try { if (WSUtils.getInstance().isReconnecting()) { - synchronized (WSUtils.getInstance()) { - RestRequestThreadPool.getInstance().isWaiting().set(true); - GrpcClientRequestReplayHelper.getInstance().isWaiting().set(true); - WSUtils.getInstance().wait(); - RestRequestThreadPool.getInstance().isWaiting().set(false); - GrpcClientRequestReplayHelper.getInstance().isWaiting().set(false); - } + logger.log(LogLevel.FINER, String.format(WS_RECONNECTING, controlCommand.getId()), RestRequestProcessor.class.getSimpleName()); + return false; } String req = StringUtils.replace(controlCommand.getArguments().get(0), NR_CSEC_VALIDATOR_HOME_TMP, OsVariablesInstance.getInstance().getOsVariables().getTmpDirectory()); req = StringUtils.replace(req, NR_CSEC_VALIDATOR_HOME_TMP_URL_ENCODED, CallbackUtils.urlEncode(OsVariablesInstance.getInstance().getOsVariables().getTmpDirectory())); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestThreadPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestThreadPool.java index e0238558e..e57670be6 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestThreadPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestThreadPool.java @@ -29,8 +29,6 @@ public class RestRequestThreadPool { private final TimeUnit timeUnit = TimeUnit.SECONDS; private final boolean allowCoreThreadTimeOut = false; - private static final AtomicBoolean isWaiting = new AtomicBoolean(false); - private final Map> processedIds = new ConcurrentHashMap(); private final Set pendingIds = ConcurrentHashMap.newKeySet(); @@ -128,10 +126,6 @@ public BlockingQueue getQueue() { return this.executor.getQueue(); } - public AtomicBoolean isWaiting() { - return isWaiting; - } - public ThreadPoolExecutor getExecutor() { return executor; } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java index 033913645..e18da9551 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/controlcommand/ControlCommandProcessor.java @@ -226,28 +226,9 @@ public void run() { */ try { AgentInfo.getInstance().getJaHealthCheck().getWebSocketConnectionStats().incrementReceivedReconnectAtWill(); + WSUtils.getInstance().setReconnecting(true); //TODO no need for draining IAST since last leg has complete ledger. logger.log(LogLevel.INFO, RECEIVED_WS_RECONNECT_COMMAND_FROM_SERVER_INITIATING_SEQUENCE, this.getClass().getName()); - if (NewRelicSecurity.getAgent().getCurrentPolicy().getVulnerabilityScan().getEnabled() && - NewRelicSecurity.getAgent().getCurrentPolicy().getVulnerabilityScan().getIastScan().getEnabled() - ) { - WSUtils.getInstance().setReconnecting(true); - while (EventSendPool.getInstance().getExecutor().getActiveCount() > 0 && !EventSendPool.getInstance().isWaiting().get()) { - Thread.sleep(100); - } - logger.log(LogLevel.FINER, WS_RECONNECT_EVENT_SEND_POOL_DRAINED, this.getClass().getName()); - - while (RestRequestThreadPool.getInstance().getExecutor().getActiveCount() > 0 && !RestRequestThreadPool.getInstance().isWaiting().get()) { - Thread.sleep(100); - } - logger.log(LogLevel.FINER, String.format("Request = %s, in process = %s", GrpcClientRequestReplayHelper.getInstance().getRequestQueue().size(), GrpcClientRequestReplayHelper.getInstance().getInProcessRequestQueue().size()), this.getClass().getName()); - while (GrpcClientRequestReplayHelper.getInstance().getRequestQueue().size() > 0 && GrpcClientRequestReplayHelper.getInstance().getInProcessRequestQueue().size() > 0 && !GrpcClientRequestReplayHelper.getInstance().isWaiting().get()) { - Thread.sleep(100); - } - logger.log(LogLevel.FINER, WS_RECONNECT_IAST_REQUEST_REPLAY_POOL_DRAINED, this.getClass().getName()); - } -// RestRequestThreadPool.getInstance().resetIASTProcessing(); -// GrpcClientRequestReplayHelper.getInstance().resetIASTProcessing(); WSClient.getInstance().close(CloseFrame.SERVICE_RESTART, "Reconnecting to service"); } catch (Throwable e) { logger.log(LogLevel.SEVERE, String.format(ERROR_WHILE_PROCESSING_RECONNECTION_CC_S_S, e.getMessage(), e.getCause()), this.getClass().getName()); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/IAgentConstants.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/IAgentConstants.java index ac86fcf2e..5a11e43d3 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/IAgentConstants.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/logging/IAgentConstants.java @@ -579,4 +579,5 @@ public interface IAgentConstants { String REQUEST_FAILURE_DUE_TO_IOEXCEPTION = "Request failure could be due to cancellation, a connectivity problem or timeout."; String FAILURE_WHILE_GRPC_REQUEST_BODY_CONVERSION = "Failure while processing gRPC Request body, body : %s "; String REQUEST_FAILURE_FOR_S_WITH_RESPONSE_CODE = "Request failure for : %s, with response : %s and response body : %s"; + } \ No newline at end of file diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java index f517a9ad1..3da76083b 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSendPool.java @@ -27,8 +27,6 @@ public class EventSendPool { private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); - private AtomicBoolean isWaiting = new AtomicBoolean(false); - private EventSendPool() { // load the settings int queueSize = QUEUE_SIZE; @@ -167,10 +165,6 @@ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } } - public AtomicBoolean isWaiting() { - return isWaiting; - } - public ThreadPoolExecutor getExecutor() { return executor; } diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSender.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSender.java index 893f5687a..889bd35e0 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSender.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/websocket/EventSender.java @@ -35,13 +35,6 @@ public EventSender(Object event) { */ @Override public Boolean call() throws Exception { - if (WSUtils.getInstance().isReconnecting()) { - synchronized (WSUtils.getInstance()) { - EventSendPool.getInstance().isWaiting().set(true); - WSUtils.getInstance().wait(); - EventSendPool.getInstance().isWaiting().set(false); - } - } if (event instanceof JavaAgentEventBean) { ((JavaAgentEventBean) event).setEventGenerationTime(System.currentTimeMillis()); } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GrpcClientRequestReplayHelper.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GrpcClientRequestReplayHelper.java index eb2eef653..9009d5bef 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GrpcClientRequestReplayHelper.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/instrumentation/helpers/GrpcClientRequestReplayHelper.java @@ -20,7 +20,6 @@ public class GrpcClientRequestReplayHelper { private final Map> processedIds = new ConcurrentHashMap(); private final Set pendingIds = ConcurrentHashMap.newKeySet(); private final Set rejectedIds = ConcurrentHashMap.newKeySet(); - private static final AtomicBoolean isWaiting = new AtomicBoolean(false); public static GrpcClientRequestReplayHelper getInstance(){ return InstanceHolder.instance; @@ -69,10 +68,6 @@ public void setGrpcRequestExecutorStarted(boolean grpcRequestExecutorStarted) { isGrpcRequestExecutorStarted = grpcRequestExecutorStarted; } - public AtomicBoolean isWaiting() { - return isWaiting; - } - public void addFuzzFailEventToQueue(FuzzRequestBean requestBean, Throwable e){ fuzzFailRequestQueue.add(Collections.singletonMap(requestBean, e)); } From 77e5ff500d0d77f540a836380ec6695671461027 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Wed, 11 Sep 2024 12:16:11 +0530 Subject: [PATCH 115/122] improve json array representation for restrict --- .../agent/security/intcodeagent/utils/RestrictionUtility.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java index 07b3a9609..c895f1457 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java @@ -270,9 +270,9 @@ private static Map> parseJsonNode(JsonNode node, String bas private static @NotNull String getBase(String baseKey, int index) { if(StringUtils.isBlank(baseKey)){ - return String.format("[%s]", index); + return "[]"; } - return String.format("%s[%s]", baseKey, index); + return String.format("%s[]", baseKey); } private static Map> parseRequestHeaders(Map headers) { From 3c679c5d41247133a1ad943b191d86b5e05dca93 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 12 Sep 2024 12:07:56 +0530 Subject: [PATCH 116/122] Use case type SQL for postgresSQL --- .../AbstractJdbc2Statement_Instrumentation.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/main/java/org/postgresql/jdbc2/AbstractJdbc2Statement_Instrumentation.java b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/main/java/org/postgresql/jdbc2/AbstractJdbc2Statement_Instrumentation.java index ba493bac3..3fb4d314f 100644 --- a/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/main/java/org/postgresql/jdbc2/AbstractJdbc2Statement_Instrumentation.java +++ b/instrumentation-security/jdbc-postgresql-8.0-312.jdbc3/src/main/java/org/postgresql/jdbc2/AbstractJdbc2Statement_Instrumentation.java @@ -77,8 +77,8 @@ private void releaseLock() { GenericHelper.releaseLock(JdbcHelper.getNrSecCustomAttribName()); } - private boolean acquireLockIfPossible(VulnerabilityCaseType httpRequest) { - return GenericHelper.acquireLockIfPossible(httpRequest, JdbcHelper.getNrSecCustomAttribName()); + private boolean acquireLockIfPossible() { + return GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.SQL_DB_COMMAND, JdbcHelper.getNrSecCustomAttribName()); } public AbstractJdbc2Statement_Instrumentation(AbstractJdbc2Connection connection, String sql, boolean isCallable, int rsType, int rsConcurrency) throws SQLException { @@ -86,7 +86,7 @@ public AbstractJdbc2Statement_Instrumentation(AbstractJdbc2Connection connection } public ResultSet executeQuery() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -107,7 +107,7 @@ public ResultSet executeQuery() throws SQLException { } public ResultSet executeQuery(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_QUERY); @@ -125,7 +125,7 @@ public ResultSet executeQuery(String sql) throws SQLException { } public int executeUpdate() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -146,7 +146,7 @@ public int executeUpdate() throws SQLException { } public int executeUpdate(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE_UPDATE); @@ -164,7 +164,7 @@ public int executeUpdate(String sql) throws SQLException { } public boolean execute() throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { if(sqlQuery == null){ @@ -185,7 +185,7 @@ public boolean execute() throws SQLException { } public boolean execute(String sql) throws SQLException { - boolean isLockAcquired = acquireLockIfPossible(VulnerabilityCaseType.HTTP_REQUEST); + boolean isLockAcquired = acquireLockIfPossible(); AbstractOperation operation = null; if(isLockAcquired) { operation = preprocessSecurityHook(sql, JdbcHelper.METHOD_EXECUTE); From b2ee82820355b955a25823c2818a1ba8576d151e Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Fri, 13 Sep 2024 10:43:11 +0530 Subject: [PATCH 117/122] Updated config changes regarding mapping parameters. --- .../NullPointerException_Instrumentation.java | 17 ---- .../newrelic/agent/security/AgentConfig.java | 83 +++++++++++-------- .../newrelic/agent/security/AgentInfo.java | 6 +- .../filelogging/FileLoggerThreadPool.java | 13 ++- .../intcodeagent/utils/CommonUtils.java | 22 +---- .../intcodeagent/utils/ResourceUtils.java | 23 +++++ .../utils/RestrictionUtility.java | 38 ++++----- .../intcodeagent/websocket/WSClient.java | 3 +- .../agent/security/util/IUtilConstants.java | 11 +++ .../newrelic/api/agent/security/Agent.java | 3 +- .../security/schema/policy/IASTScan.java | 2 - .../schema/policy/MappingParameter.java | 34 ++++++++ .../schema/policy/MappingParameters.java | 54 ++++++++---- .../schema/policy/RestrictionCriteria.java | 26 +----- 14 files changed, 197 insertions(+), 138 deletions(-) delete mode 100644 instrumentation-security/exception-handler/src/main/java/java/lang/NullPointerException_Instrumentation.java create mode 100644 newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/ResourceUtils.java create mode 100644 newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameter.java diff --git a/instrumentation-security/exception-handler/src/main/java/java/lang/NullPointerException_Instrumentation.java b/instrumentation-security/exception-handler/src/main/java/java/lang/NullPointerException_Instrumentation.java deleted file mode 100644 index ab476454a..000000000 --- a/instrumentation-security/exception-handler/src/main/java/java/lang/NullPointerException_Instrumentation.java +++ /dev/null @@ -1,17 +0,0 @@ -package java.lang; - -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.WeaveAllConstructors; - -@Weave(type = MatchType.ExactClass, originalName = "java.lang.NullPointerException") -public class NullPointerException_Instrumentation extends RuntimeException { - - @WeaveAllConstructors - public NullPointerException_Instrumentation() { - if (NewRelicSecurity.isHookProcessingActive()) { - NewRelicSecurity.getAgent().reportApplicationRuntimeError(NewRelicSecurity.getAgent().getSecurityMetaData(), this); - } - } -} 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 c10990844..a3fed3d43 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 @@ -23,6 +23,8 @@ import org.apache.commons.io.comparator.LastModifiedFileComparator; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -51,6 +53,9 @@ public class AgentConfig { public static final String ROUTE = "route"; public static final String MAPPING_PARAMETERS_ARE_REQUIRED_FOR_IAST_RESTRICTED_MODE = "Mapping Parameters are required for IAST Restricted Mode"; public static final String DEFAULT_SCAN_SCHEDULE_EXPRESSION = "0 0 0 * * ?"; + public static final String INVALID_SECURITY_CONFIGURATION_FOR_MODE_IAST_RESTRICTED = "Invalid Security Configuration for mode IAST_RESTRICTED "; + public static final String INVALID_SECURITY_CONFIGURATION = "Invalid Security Configuration "; + private static final Logger log = LoggerFactory.getLogger(AgentConfig.class); private String NR_CSEC_HOME; private String logLevel; @@ -92,6 +97,8 @@ public long instantiate() throws RestrictionModeException { osVariables = OsVariablesInstance.instantiate().getOsVariables(); logger = FileLoggerThreadPool.getInstance(); + //Do not repeat this task + logger.initialiseLogger(); iastTestIdentifier = NewRelic.getAgent().getConfig().getValue(IUtilConstants.IAST_TEST_IDENTIFIER); @@ -129,7 +136,6 @@ private void instantiateAgentMode(String groupName) throws RestrictionModeExcept case IAST_RESTRICTED: try { readIastRestrictedConfig(); - updateSkipScanParameters(); } catch (RestrictionModeException e) { System.err.println("[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled."); NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Restricted Mode Configuration. IAST Restricted Mode will be disabled."); @@ -146,6 +152,7 @@ private void instantiateAgentMode(String groupName) throws RestrictionModeExcept try { readScanSchedule(); readSkipScan(); + updateSkipScanParameters(); } catch (RestrictionModeException e){ System.err.println("[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled."); NewRelic.getAgent().getLogger().log(Level.WARNING, "[NR-CSEC-JA] Error while reading IAST Scan Configuration. Security will be disabled. Message : {0}", e.getMessage()); @@ -180,7 +187,7 @@ private void readSkipScan() throws RestrictionModeException { agentMode.getSkipScan().getIastDetectionCategory().setRxssEnabled(NewRelic.getAgent().getConfig().getValue(SKIP_RXSS, false)); agentMode.getSkipScan().getIastDetectionCategory().generateDisabledCategoriesCSV(); } catch (ClassCastException | NumberFormatException e){ - throw new RestrictionModeException("Invalid Security Configuration " + e.getMessage(), e); + throw new RestrictionModeException(INVALID_SECURITY_CONFIGURATION + e.getMessage(), e); } } @@ -209,19 +216,20 @@ private void readScanSchedule() throws RestrictionModeException { agentMode.getScanSchedule().setNextScanTime(new Date(Instant.now().toEpochMilli())); } } catch (ClassCastException | NumberFormatException e){ - throw new RestrictionModeException("Invalid Security Configuration " + e.getMessage(), e); + throw new RestrictionModeException(INVALID_SECURITY_CONFIGURATION + e.getMessage(), e); } } private void updateSkipScanParameters() { - for (MappingParameters mappingParameter : this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters()) { - if(mappingParameter.getAccountIdLocation().equals(HttpParameterLocation.HEADER)){ - this.agentMode.getSkipScan().getParameters().getHeader().add(mappingParameter.getAccountIdKey()); - } else if(mappingParameter.getAccountIdLocation().equals(HttpParameterLocation.QUERY)){ - this.agentMode.getSkipScan().getParameters().getQuery().add(mappingParameter.getAccountIdKey()); - } else if(mappingParameter.getAccountIdLocation().equals(HttpParameterLocation.BODY)){ - this.agentMode.getSkipScan().getParameters().getBody().add(mappingParameter.getAccountIdKey()); - } + + if(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getBody().isEnabled()){ + this.agentMode.getSkipScan().getParameters().getBody().addAll(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getBody().getLocations()); + } + if(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getQuery().isEnabled()){ + this.agentMode.getSkipScan().getParameters().getQuery().addAll(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getQuery().getLocations()); + } + if(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getHeader().isEnabled()){ + this.agentMode.getSkipScan().getParameters().getHeader().addAll(this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getHeader().getLocations()); } } @@ -232,32 +240,39 @@ private void readIastConfig() { } private void readIastRestrictedConfig() throws RestrictionModeException { - this.agentMode.getIastScan().setRestricted(true); - Agent.getCustomNoticeErrorParameters().put(IAST_RESTRICTED, String.valueOf(true)); - RestrictionCriteria restrictionCriteria = this.agentMode.getIastScan().getRestrictionCriteria(); - restrictionCriteria.setAccountInfo(new AccountInfo(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID))); - if(restrictionCriteria.getAccountInfo().isEmpty()) { - throw new RestrictionModeException(ACCOUNT_ID_IS_REQUIRED_FOR_IAST_RESTRICTED_MODE); - } + try { + this.agentMode.getIastScan().setRestricted(true); + Agent.getCustomNoticeErrorParameters().put(IAST_RESTRICTED, String.valueOf(true)); + RestrictionCriteria restrictionCriteria = this.agentMode.getIastScan().getRestrictionCriteria(); + restrictionCriteria.setAccountInfo(new AccountInfo(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID))); + if(restrictionCriteria.getAccountInfo().isEmpty()) { + throw new RestrictionModeException(ACCOUNT_ID_IS_REQUIRED_FOR_IAST_RESTRICTED_MODE); + } - //Mapping parameters - List> mappingParameters = NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS, Collections.emptyList()); - if(mappingParameters.isEmpty()) { - throw new RestrictionModeException(MAPPING_PARAMETERS_ARE_REQUIRED_FOR_IAST_RESTRICTED_MODE); - } - for (Map mappingParameter : mappingParameters) { - MappingParameters matchingCriteria = new MappingParameters(HttpParameterLocation.valueOf(mappingParameter.get(ACCOUNT_ID_LOCATION)), mappingParameter.get(ACCOUNT_ID_KEY)); -// MappingParameters matchingCriteria = mapper.convertValue(mappingParameter, MappingParameters.class); - restrictionCriteria.getMappingParameters().add(matchingCriteria); - } + //Mapping parameters + this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getBody().setEnabled(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_BODY_ENABLED, false)); + this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getQuery().setEnabled(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_QUERY_ENABLED, false)); + this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getHeader().setEnabled(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_HEADER_ENABLED, false)); + this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getPath().setEnabled(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_PATH_ENABLED, false)); + this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getBody().setLocations(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_BODY_LOCATION, Collections.emptyList()).stream() + .map(Object::toString) + .collect(Collectors.toList())); + this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getQuery().setLocations(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_QUERY_LOCATION, Collections.emptyList()).stream() + .map(Object::toString) + .collect(Collectors.toList())); + this.agentMode.getIastScan().getRestrictionCriteria().getMappingParameters().getHeader().setLocations(NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_MAPPING_PARAMETERS_HEADER_LOCATION, Collections.emptyList()).stream() + .map(Object::toString) + .collect(Collectors.toList())); - //Strict Criteria - List> strictCriteria = NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_STRICT, Collections.emptyList()); - for (Map strictCriterion : strictCriteria) { - StrictMappings matchingCriteria = new StrictMappings(strictCriterion.get(ROUTE), HttpParameterLocation.valueOf(strictCriterion.get(ACCOUNT_ID_LOCATION)), strictCriterion.get(ACCOUNT_ID_KEY)); - restrictionCriteria.getStrictMappings().add(matchingCriteria); + //Strict Criteria + List> strictCriteria = NewRelic.getAgent().getConfig().getValue(RESTRICTION_CRITERIA_STRICT, Collections.emptyList()); + for (Map strictCriterion : strictCriteria) { + StrictMappings matchingCriteria = new StrictMappings(strictCriterion.get(ROUTE), HttpParameterLocation.valueOf(strictCriterion.get(ACCOUNT_ID_LOCATION)), strictCriterion.get(ACCOUNT_ID_KEY)); + restrictionCriteria.getStrictMappings().add(matchingCriteria); + } + } catch (ClassCastException | NumberFormatException e){ + throw new RestrictionModeException(INVALID_SECURITY_CONFIGURATION_FOR_MODE_IAST_RESTRICTED + e.getMessage(), e); } - } private void readRaspConfig() { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentInfo.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentInfo.java index b69db9675..596ce452f 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentInfo.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentInfo.java @@ -48,7 +48,7 @@ public class AgentInfo { private BuildInfo buildInfo = new BuildInfo(); - private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); + private static FileLoggerThreadPool logger; private boolean processProtected = false; private AgentInfo() { @@ -119,6 +119,10 @@ public void setBuildInfo(BuildInfo buildInfo) { this.buildInfo = buildInfo; } + public static void initialiseLogger() { + logger = FileLoggerThreadPool.getInstance(); + } + public ApplicationInfoBean generateAppInfo(CollectorConfig config) { applicationInfo = ApplicationInfoUtils.createApplicationInfoBean(identifier, getVMPID(), applicationUUID, config); if (applicationInfo == null) { diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java index 6dcb7f362..46db8e43d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/filelogging/FileLoggerThreadPool.java @@ -32,13 +32,19 @@ public class FileLoggerThreadPool { private static OSVariables osVariables = OsVariablesInstance.getInstance().getOsVariables(); private FileLoggerThreadPool() throws IOException { + maxfiles = LogFileHelper.logFileCount(); + maxfilesize = LogFileHelper.logFileLimit()* 1024L; + } + + /** + * Initialise the logger, call this method only once + */ + public void initialiseLogger() { // load the settings int queueSize = 15000; int maxPoolSize = 1; int corePoolSize = 1; long keepAliveTime = 600; - maxfiles = LogFileHelper.logFileCount(); - maxfilesize = LogFileHelper.logFileLimit()* 1024L; TimeUnit timeUnit = TimeUnit.SECONDS; try { @@ -47,7 +53,7 @@ private FileLoggerThreadPool() throws IOException { } } catch (NumberFormatException e){} - if(!isLoggingToStdOut && StringUtils.isNotBlank(osVariables.getLogDirectory())) { + if(!isLoggingToStdOut && StringUtils.isBlank(osVariables.getLogDirectory())) { isLoggingActive = false; isInitLoggingActive = false; return; @@ -80,7 +86,6 @@ public Thread newThread(Runnable r) { return t; } }); - } 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 4bc17ee4b..2def061f0 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 @@ -1,14 +1,9 @@ package com.newrelic.agent.security.intcodeagent.utils; -import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; -import com.newrelic.api.agent.security.utils.logging.LogLevel; -import com.newrelic.api.agent.security.Agent; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -17,10 +12,9 @@ import java.util.Stack; public class CommonUtils { - - private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); - public static final String POLICY_WRITE_FAILED = "policy write failed : "; - public static final String POLICY_WRITTEN_TO_FILE = "policy written to file : "; + /** + * This class can't have a logger + */ public static SecureRandom secureRandom = new SecureRandom(); @@ -49,16 +43,6 @@ public static Boolean forceMkdirs(Path directory, String permissions) throws IOE return true; } - public static InputStream getResourceStreamFromAgentJar(String resourceName) { - try { - return new URL("jar:" + Agent.getAgentJarURL().toExternalForm() + "!/" + resourceName).openStream(); - } catch (Exception e) { - logger.log(LogLevel.SEVERE, String.format("Unable to locate resource from agent jar : %s", e.getMessage()), CommonUtils.class.getName()); - logger.log(LogLevel.FINER, "Unable to locate resource from agent jar : ", e, CommonUtils.class.getName()); - } - return null; - } - /** * Generate random int between range start to end. Both inclusive. diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/ResourceUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/ResourceUtils.java new file mode 100644 index 000000000..faa2d3f1c --- /dev/null +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/ResourceUtils.java @@ -0,0 +1,23 @@ +package com.newrelic.agent.security.intcodeagent.utils; + +import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; +import com.newrelic.api.agent.security.Agent; +import com.newrelic.api.agent.security.utils.logging.LogLevel; + +import java.io.InputStream; +import java.net.URL; + +public class ResourceUtils { + + private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance(); + + public static InputStream getResourceStreamFromAgentJar(String resourceName) { + try { + return new URL("jar:" + Agent.getAgentJarURL().toExternalForm() + "!/" + resourceName).openStream(); + } catch (Exception e) { + logger.log(LogLevel.SEVERE, String.format("Unable to locate resource from agent jar : %s", e.getMessage()), CommonUtils.class.getName()); + logger.log(LogLevel.FINER, "Unable to locate resource from agent jar : ", e, CommonUtils.class.getName()); + } + return null; + } +} diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java index b26f0015b..0128a219d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java @@ -71,29 +71,29 @@ public static boolean hasValidAccountId(RestrictionCriteria restrictionCriteria, if(!request.isRequestParametersParsed()){ parseHttpRequestParameters(request); } - for (MappingParameters mappingParameter : restrictionCriteria.getMappingParameters()) { - boolean match = false; - switch (mappingParameter.getAccountIdLocation()) { - case QUERY: - List queryParameters = getQueryString(mappingParameter.getAccountIdKey(), request.getQueryParameters()); - match = matcher(accountIds, queryParameters); - break; - case PATH: - match = matcher(accountIds, request.getPathParameters()); - break; - case HEADER: - List headerValues = getHeaderParameters(mappingParameter.getAccountIdKey(), request.getRequestHeaderParameters()); - match = matcher(accountIds, headerValues); - break; - case BODY: - List bodyValues = getBodyParameters(mappingParameter.getAccountIdKey(), request.getRequestBodyParameters()); - match = matcher(accountIds, bodyValues); - break; + + if(restrictionCriteria.getMappingParameters().getHeader().isEnabled()) { + List headerValues = restrictionCriteria.getMappingParameters().getHeader().getLocations(); + if(matcher(accountIds, headerValues)){ + return true; + } + } + if(restrictionCriteria.getMappingParameters().getQuery().isEnabled()) { + List queryValues = restrictionCriteria.getMappingParameters().getQuery().getLocations(); + if(matcher(accountIds, queryValues)){ + return true; } - if(match){ + } + if(restrictionCriteria.getMappingParameters().getPath().isEnabled()) { + if(matcher(accountIds, request.getPathParameters())){ return true; } } + if(restrictionCriteria.getMappingParameters().getBody().isEnabled()) { + List bodyValues = restrictionCriteria.getMappingParameters().getBody().getLocations(); + return matcher(accountIds, bodyValues); + } + return false; } 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 e1240b2d2..e156df9db 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 @@ -10,6 +10,7 @@ import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessorThreadPool; import com.newrelic.agent.security.intcodeagent.exceptions.SecurityNoticeError; import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; +import com.newrelic.agent.security.intcodeagent.utils.ResourceUtils; import com.newrelic.api.agent.security.utils.logging.LogLevel; import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants; import com.newrelic.agent.security.intcodeagent.utils.CommonUtils; @@ -130,7 +131,7 @@ private InputStream getCaBundleStream() throws IOException { inputStream = Files.newInputStream(Paths.get(caBundlePath)); } else { noticeErrorCustomParameters.put("ca_bundle_path", "internal-pem"); - inputStream = CommonUtils.getResourceStreamFromAgentJar("nr-custom-ca.pem"); + inputStream = ResourceUtils.getResourceStreamFromAgentJar("nr-custom-ca.pem"); } return inputStream; } 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 d04d53cc7..d40df7dba 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 @@ -37,6 +37,17 @@ public interface IUtilConstants { String RESTRICTION_CRITERIA = "security.restriction_criteria"; String RESTRICTION_CRITERIA_ACCOUNT_INFO_ACCOUNT_ID = "security.restriction_criteria.account_info.account_id_value"; String RESTRICTION_CRITERIA_MAPPING_PARAMETERS = "security.restriction_criteria.mapping_parameters"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_HEADER = RESTRICTION_CRITERIA_MAPPING_PARAMETERS + ".header"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_QUERY = RESTRICTION_CRITERIA_MAPPING_PARAMETERS + ".query"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_BODY = RESTRICTION_CRITERIA_MAPPING_PARAMETERS + ".body"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_PATH = RESTRICTION_CRITERIA_MAPPING_PARAMETERS + ".path"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_HEADER_ENABLED = RESTRICTION_CRITERIA_MAPPING_PARAMETERS_HEADER + ".enabled"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_QUERY_ENABLED = RESTRICTION_CRITERIA_MAPPING_PARAMETERS_QUERY + ".enabled"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_BODY_ENABLED = RESTRICTION_CRITERIA_MAPPING_PARAMETERS_BODY + ".enabled"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_PATH_ENABLED = RESTRICTION_CRITERIA_MAPPING_PARAMETERS_PATH + ".enabled"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_HEADER_LOCATION = RESTRICTION_CRITERIA_MAPPING_PARAMETERS_HEADER + ".location"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_QUERY_LOCATION = RESTRICTION_CRITERIA_MAPPING_PARAMETERS_QUERY + ".location"; + String RESTRICTION_CRITERIA_MAPPING_PARAMETERS_BODY_LOCATION = RESTRICTION_CRITERIA_MAPPING_PARAMETERS_BODY + ".location"; String RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS = "security.restriction_criteria.skip_scan_parameters"; String RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_HEADER = "security.restriction_criteria.skip_scan_parameters.header"; String RESTRICTION_CRITERIA_SKIP_SCAN_PARAMETERS_QUERY = "security.restriction_criteria.skip_scan_parameters.query"; 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 398e61f30..8cc1dd6b0 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 @@ -110,6 +110,7 @@ private void initialise() throws RestrictionModeException { info = AgentInfo.getInstance(); } long delay = config.instantiate(); + AgentInfo.initialiseLogger(); SchedulerHelper.getInstance().scheduleIastTrigger(this::triggerNrSecurity, delay, TimeUnit.MILLISECONDS); } @@ -228,7 +229,7 @@ private BuildInfo readCollectorBuildInfo() { BuildInfo buildInfo = new BuildInfo(); try { Properties properties = new Properties(); - properties.load(CommonUtils.getResourceStreamFromAgentJar("Agent.properties")); + properties.load(ResourceUtils.getResourceStreamFromAgentJar("Agent.properties")); buildInfo = new ObjectMapper().convertValue(properties, BuildInfo.class); } catch (Throwable e) { logger.log(LogLevel.SEVERE, String.format(CRITICAL_ERROR_UNABLE_TO_READ_BUILD_INFO_AND_VERSION_S_S, e.getMessage(), e.getCause()), this.getClass().getName()); diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java index cadba8ae5..c18a9be27 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/IASTScan.java @@ -7,9 +7,7 @@ public class IASTScan { private Boolean enabled = true; private Probing probing = new Probing(); - @JsonIgnore private Boolean restricted = false; - @JsonIgnore private RestrictionCriteria restrictionCriteria = new RestrictionCriteria(); /** diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameter.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameter.java new file mode 100644 index 000000000..f4ee7b353 --- /dev/null +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameter.java @@ -0,0 +1,34 @@ +package com.newrelic.api.agent.security.schema.policy; + +import java.util.List; + +public class MappingParameter { + + private boolean enabled; + + private List locations; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public List getLocations() { + return locations; + } + + public void setLocations(List locations) { + this.locations = locations; + } + + public MappingParameter() { + } + + public MappingParameter(boolean enabled, List locations) { + this.enabled = enabled; + this.locations = locations; + } +} diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameters.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameters.java index 2294265ba..aa34cbd90 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameters.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/MappingParameters.java @@ -4,37 +4,57 @@ public class MappingParameters { - @JsonProperty("account_id_location") - private HttpParameterLocation accountIdLocation; + private MappingParameter header; - @JsonProperty("account_id_key") - private String accountIdKey; + private MappingParameter body; + + private MappingParameter query; + + private MappingParameter path; public MappingParameters() { + this.header = new MappingParameter(); + this.body = new MappingParameter(); + this.query = new MappingParameter(); + this.path = new MappingParameter(); + } + + public MappingParameters(MappingParameter header, MappingParameter body, MappingParameter query, MappingParameter path) { + this.header = header; + this.body = body; + this.query = query; + this.path = path; + } + + public MappingParameter getHeader() { + return header; + } + + public void setHeader(MappingParameter header) { + this.header = header; } - public MappingParameters(HttpParameterLocation accountIdLocation) { - this.accountIdLocation = accountIdLocation; + public MappingParameter getBody() { + return body; } - public MappingParameters(HttpParameterLocation accountIdLocation, String accountIdKey) { - this.accountIdLocation = accountIdLocation; - this.accountIdKey = accountIdKey; + public void setBody(MappingParameter body) { + this.body = body; } - public HttpParameterLocation getAccountIdLocation() { - return accountIdLocation; + public MappingParameter getQuery() { + return query; } - public void setAccountIdLocation(HttpParameterLocation accountIdLocation) { - this.accountIdLocation = accountIdLocation; + public void setQuery(MappingParameter query) { + this.query = query; } - public String getAccountIdKey() { - return accountIdKey; + public MappingParameter getPath() { + return path; } - public void setAccountIdKey(String accountIdKey) { - this.accountIdKey = accountIdKey; + public void setPath(MappingParameter path) { + this.path = path; } } diff --git a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java index 8d87ce1c6..395011a23 100644 --- a/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java +++ b/newrelic-security-api/src/main/java/com/newrelic/api/agent/security/schema/policy/RestrictionCriteria.java @@ -5,27 +5,15 @@ public class RestrictionCriteria { - private ScanSchedule scanSchedule = new ScanSchedule(); - private AccountInfo accountInfo = new AccountInfo(); - private List mappingParameters = new ArrayList<>(); - - private SkipScanParameters skipScanParameters = new SkipScanParameters(); + private MappingParameters mappingParameters = new MappingParameters(); private List strictMappings = new ArrayList<>(); public RestrictionCriteria() { } - public ScanSchedule getScanTime() { - return scanSchedule; - } - - public void setScanTime(ScanSchedule scanSchedule) { - this.scanSchedule = scanSchedule; - } - public AccountInfo getAccountInfo() { return accountInfo; } @@ -34,22 +22,14 @@ public void setAccountInfo(AccountInfo accountInfo) { this.accountInfo = accountInfo; } - public List getMappingParameters() { + public MappingParameters getMappingParameters() { return mappingParameters; } - public void setMappingParameters(List mappingParameters) { + public void setMappingParameters(MappingParameters mappingParameters) { this.mappingParameters = mappingParameters; } - public SkipScanParameters getSkipScanParameters() { - return skipScanParameters; - } - - public void setSkipScanParameters(SkipScanParameters skipScanParameters) { - this.skipScanParameters = skipScanParameters; - } - public List getStrictMappings() { return strictMappings; } From fed109e5af915b41eec4c95a7d315f04a430df10 Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 17 Sep 2024 12:19:49 +0530 Subject: [PATCH 118/122] NR-272899: Fix for user class detection grpc --- .../newrelic/api/agent/security/Agent.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 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 dc65e8bd6..f5dcdf8b3 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 @@ -496,6 +496,7 @@ private UserClassEntity setUserClassEntityByAnnotation(StackTraceElement[] servi } private UserClassEntity setUserClassEntity(AbstractOperation operation, SecurityMetaData securityMetaData) { + boolean frameworkSpecificEntityFound = false; UserClassEntity userClassEntity = new UserClassEntity(); StackTraceElement userStackTraceElement = securityMetaData.getCustomAttribute(GenericHelper.USER_CLASS_ENTITY, StackTraceElement.class); if(userStackTraceElement == null && securityMetaData.getMetaData().getServiceTrace() != null && securityMetaData.getMetaData().getServiceTrace().length > 0){ @@ -520,21 +521,18 @@ private UserClassEntity setUserClassEntity(AbstractOperation operation, Security switch (framework){ case "vertx-web": case "GRPC": - if(i-1 >= 0) { + if(!frameworkSpecificEntityFound && i-1 >= 0) { userClassEntity = setUserClassEntityForVertx(operation, userStackTraceElement, userClassEntity, securityMetaData.getMetaData().isUserLevelServiceMethodEncountered(), i); if(userClassEntity.getUserClassElement() != null){ - return userClassEntity; + frameworkSpecificEntityFound = true; } } break; default: - 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; - } + if(userStackTraceElement != null && StringUtils.equals(stackTraceElement.getClassName(), userStackTraceElement.getClassName()) + && StringUtils.equals(stackTraceElement.getMethodName(), userStackTraceElement.getMethodName())){ + userClassEntity.setUserClassElement(stackTraceElement); + userClassEntity.setCalledByUserCode(securityMetaData.getMetaData().isUserLevelServiceMethodEncountered()); } } } @@ -544,8 +542,16 @@ private UserClassEntity setUserClassEntity(AbstractOperation operation, Security return userClassEntity; } + if (frameworkSpecificEntityFound && userClassEntity.getUserClassElement() != null && !securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod()){ + return userClassEntity; + } + + if (userClassEntity.getUserClassElement() != null){ + return userClassEntity; + } + // user class identification using annotations - if (userClassEntity.getUserClassElement() == null && securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod()) { + if (securityMetaData.getMetaData().isFoundAnnotedUserLevelServiceMethod()) { return setUserClassEntityByAnnotation(securityMetaData.getMetaData().getServiceTrace()); } From c1c18fa8ae07907ce84ebf13c3e495f589f8a6da Mon Sep 17 00:00:00 2001 From: idawda Date: Tue, 17 Sep 2024 12:29:23 +0530 Subject: [PATCH 119/122] Bump jsonVersion to 1.2.9 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9971d5819..14ae4b751 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # The agent version. agentVersion=1.4.1 -jsonVersion=1.2.5 +jsonVersion=1.2.9 # Updated exposed NR APM API version. nrAPIVersion=8.12.0 From f4b2de4eaf424298cbf9a8bd6e0456b587700977 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 19 Sep 2024 12:03:01 +0530 Subject: [PATCH 120/122] update restriction check for query param, body and headers --- .../utils/RestrictionUtility.java | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java index 0128a219d..a099c18fb 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java @@ -8,7 +8,6 @@ import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool; import com.newrelic.api.agent.security.instrumentation.helpers.ServletHelper; import com.newrelic.api.agent.security.schema.HttpRequest; -import com.newrelic.api.agent.security.schema.policy.MappingParameters; import com.newrelic.api.agent.security.schema.policy.RestrictionCriteria; import com.newrelic.api.agent.security.schema.policy.SkipScan; import com.newrelic.api.agent.security.utils.logging.LogLevel; @@ -73,13 +72,13 @@ public static boolean hasValidAccountId(RestrictionCriteria restrictionCriteria, } if(restrictionCriteria.getMappingParameters().getHeader().isEnabled()) { - List headerValues = restrictionCriteria.getMappingParameters().getHeader().getLocations(); + List headerValues = getHeaderParameters(restrictionCriteria.getMappingParameters().getHeader().getLocations(), request.getQueryParameters()); if(matcher(accountIds, headerValues)){ return true; } } if(restrictionCriteria.getMappingParameters().getQuery().isEnabled()) { - List queryValues = restrictionCriteria.getMappingParameters().getQuery().getLocations(); + List queryValues = getQueryString(restrictionCriteria.getMappingParameters().getHeader().getLocations(), request.getQueryParameters()); if(matcher(accountIds, queryValues)){ return true; } @@ -90,35 +89,49 @@ public static boolean hasValidAccountId(RestrictionCriteria restrictionCriteria, } } if(restrictionCriteria.getMappingParameters().getBody().isEnabled()) { - List bodyValues = restrictionCriteria.getMappingParameters().getBody().getLocations(); + List bodyValues = getBodyParameters(restrictionCriteria.getMappingParameters().getBody().getLocations(), request.getRequestBodyParameters()); return matcher(accountIds, bodyValues); } return false; } - private static List getBodyParameters(String accountId, Map> requestBodyParameters) { + private static List getBodyParameters(List accountIds, Map> requestBodyParameters) { if (requestBodyParameters == null || requestBodyParameters.isEmpty()) { return Collections.emptyList(); } - String lowerCaseAccountId = accountId.toLowerCase(); - return requestBodyParameters.get(lowerCaseAccountId); + + List values = new ArrayList<>(); + for (String accountId : accountIds) { + String lowerCaseAccountId = accountId.toLowerCase(); + values.addAll(requestBodyParameters.get(lowerCaseAccountId)); + } + + return values; } - private static List getHeaderParameters(String accountId, Map> requestHeaderParameters) { + private static List getHeaderParameters(List accountIds, Map> requestHeaderParameters) { if (requestHeaderParameters == null || requestHeaderParameters.isEmpty()) { return Collections.emptyList(); } - String lowerCaseAccountId = accountId.toLowerCase(); - return requestHeaderParameters.get(lowerCaseAccountId); + List values = new ArrayList<>(); + for (String accountId : accountIds) { + String lowerCaseAccountId = accountId.toLowerCase(); + values.addAll(requestHeaderParameters.get(lowerCaseAccountId)); + } + return values; } - private static List getQueryString(String accountId, Map> queryParameters) { + private static List getQueryString(List accountIds, Map> queryParameters) { if(queryParameters == null || queryParameters.isEmpty()) { return Collections.emptyList(); } - String lowerCaseAccountId = accountId.toLowerCase(); - return queryParameters.get(lowerCaseAccountId); + List values = new ArrayList<>(); + for (String accountId : accountIds) { + String lowerCaseAccountId = accountId.toLowerCase(); + values.addAll(queryParameters.get(lowerCaseAccountId)); + } + return values; } private static boolean matcher(List accountIds, List values) { From 6e01a95b89c9c405a2b626434ba4a84a7e16d138 Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 19 Sep 2024 15:44:01 +0530 Subject: [PATCH 121/122] Fix for restriction via header --- .../agent/security/intcodeagent/utils/RestrictionUtility.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java index a099c18fb..c262af40e 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java @@ -72,7 +72,7 @@ public static boolean hasValidAccountId(RestrictionCriteria restrictionCriteria, } if(restrictionCriteria.getMappingParameters().getHeader().isEnabled()) { - List headerValues = getHeaderParameters(restrictionCriteria.getMappingParameters().getHeader().getLocations(), request.getQueryParameters()); + List headerValues = getHeaderParameters(restrictionCriteria.getMappingParameters().getHeader().getLocations(), request.getRequestHeaderParameters()); if(matcher(accountIds, headerValues)){ return true; } From 0edcf36ed45ea89ce855d7e9b6a0d3be9554b69b Mon Sep 17 00:00:00 2001 From: lovesh-ap Date: Thu, 19 Sep 2024 16:16:54 +0530 Subject: [PATCH 122/122] use lower case elements --- .../intcodeagent/utils/RestrictionUtility.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java index c262af40e..b53d39ced 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/intcodeagent/utils/RestrictionUtility.java @@ -104,7 +104,9 @@ private static List getBodyParameters(List accountIds, Map values = new ArrayList<>(); for (String accountId : accountIds) { String lowerCaseAccountId = accountId.toLowerCase(); - values.addAll(requestBodyParameters.get(lowerCaseAccountId)); + if(requestBodyParameters.containsKey(lowerCaseAccountId)) { + values.addAll(requestBodyParameters.get(lowerCaseAccountId)); + } } return values; @@ -117,7 +119,9 @@ private static List getHeaderParameters(List accountIds, Map values = new ArrayList<>(); for (String accountId : accountIds) { String lowerCaseAccountId = accountId.toLowerCase(); - values.addAll(requestHeaderParameters.get(lowerCaseAccountId)); + if(requestHeaderParameters.containsKey(lowerCaseAccountId)) { + values.addAll(requestHeaderParameters.get(lowerCaseAccountId)); + } } return values; } @@ -129,7 +133,9 @@ private static List getQueryString(List accountIds, Map values = new ArrayList<>(); for (String accountId : accountIds) { String lowerCaseAccountId = accountId.toLowerCase(); - values.addAll(queryParameters.get(lowerCaseAccountId)); + if(queryParameters.containsKey(lowerCaseAccountId)) { + values.addAll(queryParameters.get(lowerCaseAccountId)); + } } return values; } @@ -341,7 +347,7 @@ private static void putHeaderParameter(String key, String value, Map> parseQueryParameters(String url) { @@ -367,7 +373,7 @@ private static Map> queryParamKeyValueGenerator(String quer List values = new ArrayList<>(); values.add(StringUtils.lowerCase(value)); values.add(StringUtils.lowerCase(ServletHelper.urlDecode(value))); - queryParameters.put(key, values); + queryParameters.put(StringUtils.lowerCase(key), values); } return queryParameters; }