Skip to content

Commit

Permalink
Merge branch 'refs/heads/main' into feature/transitive-api-skip
Browse files Browse the repository at this point in the history
# Conflicts:
#	newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java
  • Loading branch information
lovesh-ap committed Dec 17, 2024
2 parents 9a258ed + fe0ce16 commit 25e2db0
Show file tree
Hide file tree
Showing 405 changed files with 8,593 additions and 3,291 deletions.
19 changes: 19 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ 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.6.0] - 2024-12-16
### Adds
- [PR-329](https://github.com/newrelic/csec-java-agent/pull/329) Apache Pekko Server Support: The security agent now supports Apache Pekko Server version 1.0.0 and newer, compatible with Scala 2.13 and above. [NR-308780](https://new-relic.atlassian.net/browse/NR-308780), [NR-308781](https://new-relic.atlassian.net/browse/NR-308781), [NR-308791](https://new-relic.atlassian.net/browse/NR-308791), [NR-308792](https://new-relic.atlassian.net/browse/NR-308792) [NR-308782](https://new-relic.atlassian.net/browse/NR-308782)
- [PR-228](https://github.com/newrelic/csec-java-agent/pull/228) HTTP4s Ember Server Support: Added support for HTTP4s Ember Server version 0.23 and newer, compatible with Scala 2.12 and above. [NR-293957](https://new-relic.atlassian.net/browse/NR-293957), [NR-293847](https://new-relic.atlassian.net/browse/NR-293847), [NR-293844](https://new-relic.atlassian.net/browse/NR-293844)
- [PR-344](https://github.com/newrelic/csec-java-agent/pull/344) HTTP4s Blaze Server Support: The security agent now supports HTTP4s Blaze Server version 0.21 and newer, compatible with Scala 2.12 and above. [NR-325523](https://new-relic.atlassian.net/browse/NR-325523), [NR-325525](https://new-relic.atlassian.net/browse/NR-325525), [NR-293846](https://new-relic.atlassian.net/browse/NR-293846)
- [PR-228](https://github.com/newrelic/csec-java-agent/pull/228) HTTP4s Ember Client Support: Introduced support for HTTP4s Ember Client version 0.23 and above, compatible with Scala 2.12 and above. [NR-307676](https://new-relic.atlassian.net/browse/NR-307676)
- [PR-346](https://github.com/newrelic/csec-java-agent/pull/346) HTTP4s Blaze Client Support: Added support for HTTP4s Blaze Client version 0.21 and newer, compatible with Scala 2.12 and above. [NR-325526](https://new-relic.atlassian.net/browse/NR-325526), [NR-325527](https://new-relic.atlassian.net/browse/NR-325527)
- [PR-363](https://github.com/newrelic/csec-java-agent/pull/363) GraphQL Support: GraphQL support is now enabled by default.

### Changes
- [PR-331](https://github.com/newrelic/csec-java-agent/pull/331) REST Client Update for IAST Request Replay: Migrated to utilize the Apache HTTP Client for enhanced request replay functionality. [NR-283130](https://new-relic.atlassian.net/browse/NR-283130)
- [PR-311](https://github.com/newrelic/csec-java-agent/pull/311) Status File Removed: The status file used for debugging has been eliminated. All debugging capabilities have been integrated into Init Logging or the Error Inbox. [NR-297214](https://new-relic.atlassian.net/browse/NR-297214)
- [PR-356](https://github.com/newrelic/csec-java-agent/pull/356) Code Optimization: Optimized code to minimize the overhead of the Security Agent in relation to the APM Agent. [NR-338596](https://new-relic.atlassian.net/browse/NR-338596)

### Fixes
- [PR-352](https://github.com/newrelic/csec-java-agent/pull/352) Corrected the issue regarding inaccurate user class details in the mule-demo-app. [NR-336715](https://new-relic.atlassian.net/browse/NR-336715)
- [PR-355](https://github.com/newrelic/csec-java-agent/pull/355) Improved logging for scenarios where delay is set to a negative value. [NR-338578](https://new-relic.atlassian.net/browse/NR-338578)


## [1.5.1] - 2024-11-9
### New features
- [PR-350](https://github.com/newrelic/csec-java-agent/pull/350) IAST support for CI/CD.
Expand Down
4 changes: 3 additions & 1 deletion buildSrc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ dependencies {
implementation("org.ow2.asm:asm-commons:9.2")

// Shadow is used here because several classes implement the Transformer interface
implementation("com.github.jengelman.gradle.plugins:shadow:6.0.0")
implementation("com.github.jengelman.gradle.plugins:shadow:6.0.0") {
exclude(group: "org.codehaus.plexus", module: "plexus-utils")
}

// Reflections and GSON are used for building the manifest of annotated classes.
implementation("org.reflections:reflections:0.9.11")
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# The agent version.
agentVersion=1.5.1
agentVersion=1.6.0
jsonVersion=1.2.9
# Updated exposed NR APM API version.
nrAPIVersion=8.12.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,23 @@

package akka.http.scaladsl

import akka.Done
import akka.http.scaladsl.model.{HttpEntity, HttpResponse}
import akka.http.scaladsl.server.AkkaCoreUtils
import akka.stream.Materializer
import akka.stream.javadsl.Source
import akka.stream.scaladsl.Sink
import akka.util.ByteString
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.exceptions.NewRelicSecurityException
import com.newrelic.api.agent.security.utils.logging.LogLevel
import com.newrelic.api.agent.{NewRelic, Token}

import java.lang
import scala.concurrent.{ExecutionContext, Future}
import scala.runtime.AbstractFunction1

class AkkaResponseHelper extends AbstractFunction1[HttpResponse, HttpResponse] {

override def apply(httpResponse: HttpResponse): HttpResponse = {
try {
val stringResponse = new lang.StringBuilder()
val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible()
val isLockAquired = GenericHelper.acquireLockIfPossible(AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME);
stringResponse.append(httpResponse.entity.asInstanceOf[HttpEntity.Strict].getData().decodeString("utf-8"))
AkkaCoreUtils.postProcessHttpRequest(isLockAquired, stringResponse, httpResponse.entity.contentType.toString(), this.getClass.getName, "apply", NewRelic.getAgent.getTransaction.getToken())
} catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,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;
Expand All @@ -26,37 +27,10 @@ public class AkkaCoreUtils {
public static final String AKKA_HTTP_10_0_0 = "AKKA_HTTP_10.0.0";
private static final String X_FORWARDED_FOR = "x-forwarded-for";
private static final String EMPTY = "";
public static final String QUESTION_MARK = "?";

public static boolean isServletLockAcquired() {
try {
return NewRelicSecurity.isHookProcessingActive() &&
Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(getNrSecCustomAttribName(), Boolean.class));
} catch (Throwable ignored) {}
return false;
}

public static void releaseServletLock() {
try {
if(NewRelicSecurity.isHookProcessingActive()) {
NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), null);
}
} catch (Throwable ignored){}
}

private static String getNrSecCustomAttribName() {
return NR_SEC_CUSTOM_ATTRIB_NAME;
}
private static final String QUESTION_MARK = "?";

public static boolean acquireServletLockIfPossible() {
try {
if (NewRelicSecurity.isHookProcessingActive() &&
!isServletLockAcquired()) {
NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), true);
return true;
}
} catch (Throwable ignored){}
return false;
return GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, NR_SEC_CUSTOM_ATTRIB_NAME);
}

public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder responseBody, String contentType, String className, String methodName, Token token) {
Expand Down Expand Up @@ -87,7 +61,7 @@ public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringB
}
} finally {
if(isServletLockAcquired){
releaseServletLock();
GenericHelper.releaseLock(NR_SEC_CUSTOM_ATTRIB_NAME);
}
}
}
Expand All @@ -105,16 +79,12 @@ public static void preProcessHttpRequest (Boolean isServletLockAcquired, HttpReq
SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData();

com.newrelic.api.agent.security.schema.HttpRequest securityRequest = securityMetaData.getRequest();
if (securityRequest.isRequestParsed()) {
return;
}

AgentMetaData securityAgentMetaData = securityMetaData.getMetaData();

securityRequest.setMethod(httpRequest.method().value());
//TODO Client IP and PORT extraction is pending

// securityRequest.setClientIP();
securityRequest.setServerPort(httpRequest.getUri().port());

processHttpRequestHeader(httpRequest, securityRequest);
Expand Down Expand Up @@ -144,8 +114,8 @@ public static void preProcessHttpRequest (Boolean isServletLockAcquired, HttpReq
NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, AKKA_HTTP_10_0_0, ignored.getMessage()), ignored, AkkaCoreUtils.class.getName());
}
finally {
if(isServletLockAcquired()){
releaseServletLock();
if(GenericHelper.isLockAcquired(AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME)){
GenericHelper.releaseLock(NR_SEC_CUSTOM_ATTRIB_NAME);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ import akka.http.scaladsl.model.HttpEntity
import akka.stream.javadsl.Source
import akka.stream.scaladsl.Sink
import akka.util.ByteString

import java.util.concurrent.atomic.AtomicBoolean
import java.util.logging.Level
import com.newrelic.api.agent.{NewRelic, Trace}
import com.newrelic.api.agent.security.NewRelicSecurity
import com.newrelic.api.agent.security.utils.logging.LogLevel
import com.newrelic.api.agent.{NewRelic, Trace}

import java.lang
import scala.collection.mutable
import java.util.concurrent.atomic.AtomicBoolean
import java.util.logging.Level
import scala.concurrent.Future
import scala.runtime.AbstractFunction1

object CsecAkkaHttpContextFunction {

final val retransformed = new AtomicBoolean(false)
private final val retransformed = new AtomicBoolean(false)

def contextWrapper(original: Function1[RequestContext, Future[RouteResult]]): Function1[RequestContext, Future[RouteResult]] = {
if (retransformed.compareAndSet(false, true)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,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;
Expand All @@ -28,37 +29,10 @@ public class AkkaCoreUtils {

private static final String X_FORWARDED_FOR = "x-forwarded-for";
private static final String EMPTY = "";
public static final String QUESTION_MARK = "?";

public static boolean isServletLockAcquired() {
try {
return NewRelicSecurity.isHookProcessingActive() &&
Boolean.TRUE.equals(NewRelicSecurity.getAgent().getSecurityMetaData().getCustomAttribute(getNrSecCustomAttribName(), Boolean.class));
} catch (Throwable ignored) {}
return false;
}

public static void releaseServletLock() {
try {
if(NewRelicSecurity.isHookProcessingActive()) {
NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), null);
}
} catch (Throwable ignored){}
}

private static String getNrSecCustomAttribName() {
return NR_SEC_CUSTOM_ATTRIB_NAME;
}
private static final String QUESTION_MARK = "?";

public static boolean acquireServletLockIfPossible() {
try {
if (NewRelicSecurity.isHookProcessingActive() &&
!isServletLockAcquired()) {
NewRelicSecurity.getAgent().getSecurityMetaData().addCustomAttribute(getNrSecCustomAttribName(), true);
return true;
}
} catch (Throwable ignored){}
return false;
return GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, NR_SEC_CUSTOM_ATTRIB_NAME);
}

public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringBuilder response, String contentType, int responseCode, String className, String methodName, Token token) {
Expand Down Expand Up @@ -94,7 +68,7 @@ public static void postProcessHttpRequest(Boolean isServletLockAcquired, StringB
NewRelicSecurity.getAgent().reportIncident(LogLevel.SEVERE, String.format(GenericHelper.REGISTER_OPERATION_EXCEPTION_MESSAGE, AKKA_HTTP_CORE_10_0, e.getMessage()), e, AkkaCoreUtils.class.getName());
} finally {
if(isServletLockAcquired){
releaseServletLock();
GenericHelper.releaseLock(NR_SEC_CUSTOM_ATTRIB_NAME);
}
}
}
Expand All @@ -121,7 +95,6 @@ public static void preProcessHttpRequest (Boolean isServletLockAcquired, HttpReq
securityRequest.setMethod(httpRequest.method().value());
//TODO Client IP and PORT extraction is pending

// securityRequest.setClientIP();
securityRequest.setServerPort(httpRequest.getUri().port());

processHttpRequestHeader(httpRequest, securityRequest);
Expand Down Expand Up @@ -150,13 +123,13 @@ public static void preProcessHttpRequest (Boolean isServletLockAcquired, HttpReq
NewRelicSecurity.getAgent().log(LogLevel.WARNING, String.format(GenericHelper.ERROR_GENERATING_HTTP_REQUEST, AKKA_HTTP_CORE_10_0, ignored.getMessage()), ignored, AkkaCoreUtils.class.getName());
}
finally {
if(isServletLockAcquired()){
releaseServletLock();
if(GenericHelper.isLockAcquired(NR_SEC_CUSTOM_ATTRIB_NAME)){
GenericHelper.releaseLock(NR_SEC_CUSTOM_ATTRIB_NAME);
}
}
}

public static String getTraceHeader(Map<String, String> headers) {
private static String getTraceHeader(Map<String, String> headers) {
String data = EMPTY;
if (headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER) || headers.containsKey(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER.toLowerCase())) {
data = headers.get(ServletHelper.CSEC_DISTRIBUTED_TRACING_HEADER);
Expand All @@ -167,7 +140,7 @@ public static String getTraceHeader(Map<String, String> headers) {
return data;
}

public static void processHttpRequestHeader(HttpRequest request, com.newrelic.api.agent.security.schema.HttpRequest securityRequest){
private static void processHttpRequestHeader(HttpRequest request, com.newrelic.api.agent.security.schema.HttpRequest securityRequest){
Iterator<HttpHeader> headers = request.getHeaders().iterator();
while (headers.hasNext()) {
boolean takeNextValue = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,6 @@ private static void registerExitOperation(boolean isProcessingAllowed, AbstractO

private AbstractOperation preprocessSecurityHook(HttpRequest httpRequest, String methodName) {
try {
SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData();
if (!NewRelicSecurity.isHookProcessingActive() || securityMetaData.getRequest().isEmpty()) {
return null;
}

// Generate required URL
URI methodURI = null;
String uri = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ public InetSocketAddress localAddress() {

@WeaveAllConstructors
public ServerBinding() {
// AgentBridge.getAgent().getLogger().log(Level.FINE, "Setting akka-http port to: {0,number,#}", localAddress().getPort());
// AgentBridge.publicApi.setAppServerPort(localAddress().getPort());
// AgentBridge.publicApi.setServerInfo("Akka HTTP", ManifestUtils.getVersionFromManifest(getClass(), "akka-http-core", "10.2.0"));

NewRelicSecurity.getAgent().setApplicationConnectionConfig(localAddress().getPort(), "http");
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ object ResponseFutureHelper {
try {
val stringResponse: lang.StringBuilder = new lang.StringBuilder();
val dataBytes: Source[ByteString, _] = response.entity.getDataBytes()
val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible();
val isLockAquired = GenericHelper.acquireLockIfPossible(AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME);
val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString =>
val chunk = byteString.utf8String
stringResponse.append(chunk)
Expand Down Expand Up @@ -61,7 +61,7 @@ object ResponseFutureHelper {
try {
val stringResponse: lang.StringBuilder = new lang.StringBuilder();
val dataBytes: Source[ByteString, _] = httpResponse.entity.getDataBytes()
val isLockAquired = AkkaCoreUtils.acquireServletLockIfPossible();
val isLockAquired = GenericHelper.acquireLockIfPossible(AkkaCoreUtils.NR_SEC_CUSTOM_ATTRIB_NAME);
val sink: Sink[ByteString, Future[Done]] = Sink.foreach[ByteString] { byteString =>
val chunk = byteString.utf8String
stringResponse.append(chunk)
Expand Down
Loading

0 comments on commit 25e2db0

Please sign in to comment.