Skip to content

Commit

Permalink
Merge pull request #229 from newrelic/hotfix/release/1.2.1
Browse files Browse the repository at this point in the history
CSEC Java Agent Public Release Version 1.2.1
  • Loading branch information
lovesh-ap authored Apr 19, 2024
2 parents 26438d1 + b7bb813 commit 65371c7
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 111 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/X-Reusable-Build-Security-Agent.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
java-version: [ 8, 11, 17 ]
java-version: [ 8 ]
# java-version: [ 8, 11, 17 ]

steps:
- name: Checkout CSEC Repo
Expand Down
9 changes: 9 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ Noteworthy changes to the agent are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.2.1] - 2024-4-19
### Fixes
- [NR-259467](https://new-relic.atlassian.net/browse/NR-259467) Fix issue of nested event generation from CSEC's agent itself [PR-230](https://github.com/newrelic/csec-java-agent/pull/230)

### Changes
- [NR-256459](https://new-relic.atlassian.net/browse/NR-256459) Exclude JAX RS 4.0.0-M2 version from Instrumentation [PR-231](https://github.com/newrelic/csec-java-agent/pull/231)
- [NR-256461](https://new-relic.atlassian.net/browse/NR-256461) Exclude mssql-jdbc version 12.7.0 from Instrumentation [PR-232](https://github.com/newrelic/csec-java-agent/pull/232)
- [NR-260369](https://new-relic.atlassian.net/browse/NR-260369) Dependency version bump of commons-compress:1.21 to commons-compress:1.26.0

## [1.2.0] - 2024-3-28
### Changes
- Json Version bump to 1.2.0 due to [NR-235776](https://new-relic.atlassian.net/browse/NR-235776) implementation.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The IAST capability should only be used in pre-production environments and never

## **Installation**

This project is built and published as a dependency for use in [newrelic-java-agent](https://github.com/newrelic/newrelic-java-agent) only. Hence this can not be used directly. Typically, most users use the version auto-installed by the APM agent. You can see agent install instructions [here](https://github.com/newrelic/java-newrelic#installation-and-getting-started).
This project is built and published as a dependency for use in [newrelic-java-agent](https://github.com/newrelic/newrelic-java-agent) only. Hence this can not be used directly. Typically, most users use the version auto-installed by the APM agent. You can see agent install instructions [here](https://docs.newrelic.com/docs/iast/install/).

## **Supported Java Versions**
- Java version 8 and above
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.2.0
agentVersion=1.2.1
jsonVersion=1.2.0
# Updated exposed NR APM API version.
nrAPIVersion=8.4.0
Expand Down
1 change: 1 addition & 0 deletions instrumentation-security/jax-rs-3.0/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jar {

verifyInstrumentation {
passesOnly 'jakarta.ws.rs:jakarta.ws.rs-api:[3.0-M1,)'
excludeRegex '.*-M[0-9]+'
}

compileJava {
Expand Down
2 changes: 1 addition & 1 deletion instrumentation-security/jdbc-sqlserver/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jar {
}

verifyInstrumentation {
passes("com.microsoft.sqlserver:mssql-jdbc:[0,)")
passes("com.microsoft.sqlserver:mssql-jdbc:[0,12.7.0)")
excludeRegex(".*jre9.*")
excludeRegex(".*jre1\\d.*")
excludeRegex(".*preview.*")
Expand Down
2 changes: 1 addition & 1 deletion newrelic-security-agent/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ dependencies {
shadowIntoJar 'commons-io:commons-io:2.7'
shadowIntoJar 'org.apache.commons:commons-text:1.10.0'
shadowIntoJar 'commons-net:commons-net:3.9.0'
shadowIntoJar 'org.apache.commons:commons-compress:1.21'
shadowIntoJar 'org.apache.commons:commons-compress:1.26.0'
shadowIntoJar 'com.squareup.okhttp3:okhttp:4.10.0'
shadowIntoJar 'org.apache.commons:commons-collections4:4.4'
shadowIntoJar 'org.unbescape:unbescape:1.1.6.RELEASE'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool;
import com.newrelic.agent.security.intcodeagent.filelogging.LogFileHelper;
import com.newrelic.agent.security.intcodeagent.utils.EncryptorUtils;
import com.newrelic.api.agent.security.instrumentation.helpers.*;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import com.newrelic.agent.security.intcodeagent.logging.HealthCheckScheduleThread;
import com.newrelic.agent.security.intcodeagent.logging.IAgentConstants;
Expand All @@ -22,10 +23,6 @@
import com.newrelic.agent.security.util.IUtilConstants;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Transaction;
import com.newrelic.api.agent.security.instrumentation.helpers.GrpcHelper;
import com.newrelic.api.agent.security.instrumentation.helpers.AppServerInfoHelper;
import com.newrelic.api.agent.security.instrumentation.helpers.InstrumentedClass;
import com.newrelic.api.agent.security.instrumentation.helpers.LowSeverityHelper;
import com.newrelic.api.agent.security.schema.*;
import com.newrelic.api.agent.security.schema.operation.RXSSOperation;
import com.newrelic.api.agent.security.schema.policy.AgentPolicy;
Expand Down Expand Up @@ -249,60 +246,69 @@ private void deactivateSecurityServices(){
@Override
public void registerOperation(AbstractOperation operation) {
// added to fetch request/response in case of grpc requests
SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData();
if (securityMetaData!=null && securityMetaData.getRequest().getIsGrpc()){
securityMetaData.getRequest().setBody(
new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_REQUEST_DATA, List.class))));
securityMetaData.getResponse().setResponseBody(
new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_RESPONSE_DATA, List.class))));
}
// end
boolean lockAcquired = ThreadLocalLockHelper.acquireLock();
try {
if(lockAcquired) {
SecurityMetaData securityMetaData = NewRelicSecurity.getAgent().getSecurityMetaData();
if (securityMetaData != null && securityMetaData.getRequest().getIsGrpc()) {
securityMetaData.getRequest().setBody(
new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_REQUEST_DATA, List.class))));
securityMetaData.getResponse().setResponseBody(
new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_RESPONSE_DATA, List.class))));
}
// end

if (operation == null || operation.isEmpty()) {
return;
}
String executionId = ExecutionIDGenerator.getExecutionId();
operation.setExecutionId(executionId);
operation.setStartTime(Instant.now().toEpochMilli());
if(securityMetaData!=null && securityMetaData.getFuzzRequestIdentifier().getK2Request()){
logger.log(LogLevel.FINEST, String.format("New Event generation with id %s of type %s", operation.getExecutionId(), operation.getClass().getSimpleName()), Agent.class.getName());
}
if (operation instanceof RXSSOperation) {
operation.setStackTrace(securityMetaData.getMetaData().getServiceTrace());
} else {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
operation.setStackTrace(Arrays.copyOfRange(trace, 2, trace.length));
}
if (operation == null || operation.isEmpty()) {
return;
}
String executionId = ExecutionIDGenerator.getExecutionId();
operation.setExecutionId(executionId);
operation.setStartTime(Instant.now().toEpochMilli());
if (securityMetaData != null && securityMetaData.getFuzzRequestIdentifier().getK2Request()) {
logger.log(LogLevel.FINEST, String.format("New Event generation with id %s of type %s", operation.getExecutionId(), operation.getClass().getSimpleName()), Agent.class.getName());
}
if (operation instanceof RXSSOperation) {
operation.setStackTrace(securityMetaData.getMetaData().getServiceTrace());
} else {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
operation.setStackTrace(Arrays.copyOfRange(trace, 2, trace.length));
}

// added to fetch request/response in case of grpc requests
if (securityMetaData.getRequest().getIsGrpc()){
securityMetaData.getRequest().setBody(
new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_REQUEST_DATA, List.class))));
securityMetaData.getResponse().setResponseBody(
new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_RESPONSE_DATA, List.class))));
}
// added to fetch request/response in case of grpc requests
if (securityMetaData.getRequest().getIsGrpc()) {
securityMetaData.getRequest().setBody(
new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_REQUEST_DATA, List.class))));
securityMetaData.getResponse().setResponseBody(
new StringBuilder(JsonConverter.toJSON(securityMetaData.getCustomAttribute(GrpcHelper.NR_SEC_GRPC_RESPONSE_DATA, List.class))));
}

if(checkIfNRGeneratedEvent(operation)) {
logger.log(LogLevel.FINEST, DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL +
JsonConverter.toJSON(operation),
Agent.class.getName());
return;
}
if (checkIfNRGeneratedEvent(operation)) {
logger.log(LogLevel.FINEST, DROPPING_EVENT_AS_IT_WAS_GENERATED_BY_K_2_INTERNAL_API_CALL +
JsonConverter.toJSON(operation),
Agent.class.getName());
return;
}

logIfIastScanForFirstTime(securityMetaData.getFuzzRequestIdentifier(), securityMetaData.getRequest());
logIfIastScanForFirstTime(securityMetaData.getFuzzRequestIdentifier(), securityMetaData.getRequest());

setRequiredStackTrace(operation, securityMetaData);
operation.setUserClassEntity(setUserClassEntity(operation, securityMetaData));
processStackTrace(operation);
setRequiredStackTrace(operation, securityMetaData);
operation.setUserClassEntity(setUserClassEntity(operation, securityMetaData));
processStackTrace(operation);
// boolean blockNeeded = checkIfBlockingNeeded(operation.getApiID());
// securityMetaData.getMetaData().setApiBlocked(blockNeeded);
if (needToGenerateEvent(operation.getApiID())) {
DispatcherPool.getInstance().dispatchEvent(operation, securityMetaData);
if (!firstEventProcessed.get()) {
logger.logInit(LogLevel.INFO,
String.format(EVENT_ZERO_PROCESSED, securityMetaData.getRequest()),
this.getClass().getName());
firstEventProcessed.set(true);
if (needToGenerateEvent(operation.getApiID())) {
DispatcherPool.getInstance().dispatchEvent(operation, securityMetaData);
if (!firstEventProcessed.get()) {
logger.logInit(LogLevel.INFO,
String.format(EVENT_ZERO_PROCESSED, securityMetaData.getRequest()),
this.getClass().getName());
firstEventProcessed.set(true);
}
}
}
} finally {
if(lockAcquired){
ThreadLocalLockHelper.releaseLock();
}
}
}
Expand Down Expand Up @@ -439,21 +445,30 @@ private static void setAPIId(AbstractOperation operation, List<Integer> traceFor

@Override
public void registerExitEvent(AbstractOperation operation) {
if (operation == null) {
return;
}
K2RequestIdentifier k2RequestIdentifier = NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier();
HttpRequest request = NewRelicSecurity.getAgent().getSecurityMetaData().getRequest();

// TODO: Generate for only native payloads
if (!request.isEmpty() && !operation.isEmpty() && k2RequestIdentifier.getK2Request()) {
if (StringUtils.equals(k2RequestIdentifier.getApiRecordId(), operation.getApiID())
&& StringUtils.equals(k2RequestIdentifier.getNextStage().getStatus(), IAgentConstants.VULNERABLE)) {
ExitEventBean exitEventBean = new ExitEventBean(operation.getExecutionId(), operation.getCaseType().getCaseType());
exitEventBean.setK2RequestIdentifier(k2RequestIdentifier.getRaw());
logger.log(LogLevel.FINER, "Exit event : " + exitEventBean, this.getClass().getName());
DispatcherPool.getInstance().dispatchExitEvent(exitEventBean);
AgentInfo.getInstance().getJaHealthCheck().incrementExitEventSentCount();
boolean lockAcquired = ThreadLocalLockHelper.acquireLock();
try {
if(lockAcquired) {
if (operation == null) {
return;
}
K2RequestIdentifier k2RequestIdentifier = NewRelicSecurity.getAgent().getSecurityMetaData().getFuzzRequestIdentifier();
HttpRequest request = NewRelicSecurity.getAgent().getSecurityMetaData().getRequest();

// TODO: Generate for only native payloads
if (!request.isEmpty() && !operation.isEmpty() && k2RequestIdentifier.getK2Request()) {
if (StringUtils.equals(k2RequestIdentifier.getApiRecordId(), operation.getApiID())
&& StringUtils.equals(k2RequestIdentifier.getNextStage().getStatus(), IAgentConstants.VULNERABLE)) {
ExitEventBean exitEventBean = new ExitEventBean(operation.getExecutionId(), operation.getCaseType().getCaseType());
exitEventBean.setK2RequestIdentifier(k2RequestIdentifier.getRaw());
logger.log(LogLevel.FINER, "Exit event : " + exitEventBean, this.getClass().getName());
DispatcherPool.getInstance().dispatchExitEvent(exitEventBean);
AgentInfo.getInstance().getJaHealthCheck().incrementExitEventSentCount();
}
}
}
} finally {
if(lockAcquired){
ThreadLocalLockHelper.releaseLock();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package com.newrelic.api.agent.security;

import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.security.instrumentation.helpers.ThreadLocalLockHelper;
import com.newrelic.api.agent.security.schema.SecurityMetaData;
import org.apache.commons.lang3.StringUtils;

Expand All @@ -34,7 +35,7 @@ public static SecurityAgent getAgent(){
* {@code false} otherwise.
*/
public static boolean isHookProcessingActive(){
return isAgentInitComplete && Agent.getInstance().isSecurityActive() && !isInternalThread()
return !ThreadLocalLockHelper.isLockHeldByCurrentThread() && isAgentInitComplete && Agent.getInstance().isSecurityActive() && !isInternalThread()
&& NewRelic.getAgent().getTransaction() != null
&& NewRelic.getAgent().getTransaction().getSecurityMetaData() instanceof SecurityMetaData;
// (Agent.getInstance().getSecurityMetaData() != null);
Expand Down
Loading

0 comments on commit 65371c7

Please sign in to comment.