Skip to content

Commit 4b5b84c

Browse files
authored
Merge pull request #354 from newrelic/release/v1.5.1
CSEC Java Agent Release Version 1.5.1
2 parents 3873293 + 0f57b2f commit 4b5b84c

File tree

23 files changed

+1462
-23
lines changed

23 files changed

+1462
-23
lines changed

Changelog.md

+28
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,34 @@ Noteworthy changes to the agent are documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [1.5.1] - 2024-11-9
8+
### New features
9+
- [PR-350](https://github.com/newrelic/csec-java-agent/pull/350) IAST support for CI/CD.
10+
Configuration via yaml:
11+
```yaml
12+
security:
13+
# This configuration allows users to specify a unique test identifier when running IAST Scan with CI/CD
14+
iast_test_identifier: 'run-id'
15+
16+
scan_controllers:
17+
# This configuration allows users to the number of application instances for a specific entity where IAST analysis is performed.
18+
scan_instance_count: 0 # Values are 1 or 0, 0 signifies run on all application instances
19+
```
20+
- [PR-297](https://github.com/newrelic/csec-java-agent/pull/297), [PR-294](https://github.com/newrelic/csec-java-agent/pull/294), [PR-337](https://github.com/newrelic/csec-java-agent/pull/337) Detect route of an incoming request for Sun-Net-Httpserver, Netty Reactor, Apache Struts2 and Grails Framework. [NR-277771](https://new-relic.atlassian.net/browse/NR-277771), [NR-283914](https://new-relic.atlassian.net/browse/NR-283914), [NR-313390](https://new-relic.atlassian.net/browse/NR-313390), [NR-313392](https://new-relic.atlassian.net/browse/NR-313392)
21+
- [PR-297](https://github.com/newrelic/csec-java-agent/pull/297), [PR-298](https://github.com/newrelic/csec-java-agent/pull/298) HTTP Response Detection in sun-net-httpserver and mule server [NR-277771](https://new-relic.atlassian.net/browse/NR-277771), [NR-277770](https://new-relic.atlassian.net/browse/NR-277770)
22+
- [PR-335](https://github.com/newrelic/csec-java-agent/pull/335) Added request URI to application runtime error event, enhancing error logging and debugging capabilities. [NR-315194](https://new-relic.atlassian.net/browse/NR-315194)
23+
- [PR-342](https://github.com/newrelic/csec-java-agent/pull/342) Report APM's trace.id and span.id in all outgoing events. [NR-321827](https://new-relic.atlassian.net/browse/NR-321827)
24+
- [PR-347](https://github.com/newrelic/csec-java-agent/pull/347) Limiting the supported version range for GraalVM.JS, due to the new version release on Sep 17, 2024. [NR-332546](https://new-relic.atlassian.net/browse/NR-332546)
25+
- [PR-347](https://github.com/newrelic/csec-java-agent/pull/347) Limiting the supported version range for Lettuce, due to the new version release on Oct 31, 2024. [NR-332546](https://new-relic.atlassian.net/browse/NR-332546)
26+
27+
### Fixes
28+
- [PR-340](https://github.com/newrelic/csec-java-agent/pull/340) Detect correct user class in GraphQL [NR-319863](https://new-relic.atlassian.net/browse/NR-319863)
29+
- [PR-339](https://github.com/newrelic/csec-java-agent/pull/339) Fix minor bug with exclude_from_iast_scan.header while parsing of header. [NR-319858](https://new-relic.atlassian.net/browse/NR-319858)
30+
31+
### Deprecations
32+
- 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)
33+
34+
735
## [1.5.0] - 2024-9-25
836
### New features
937
- Json Version bump to 1.2.9.

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# The agent version.
2-
agentVersion=1.5.0
2+
agentVersion=1.5.1
33
jsonVersion=1.2.9
44
# Updated exposed NR APM API version.
55
nrAPIVersion=8.12.0

instrumentation-security/mongodb-3.0/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public static AbstractOperation recordMongoOperation(BsonDocument command, Strin
5252
if (NewRelicSecurity.isHookProcessingActive() &&
5353
!NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() && command != null) {
5454
operation = new NoSQLOperation(command.toJson(), typeOfOperation, klassName, methodName);
55+
NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3);
5556
NewRelicSecurity.getAgent().registerOperation(operation);
5657
}
5758
} catch (Throwable e) {

instrumentation-security/mongodb-3.6/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public static AbstractOperation recordMongoOperation(BsonDocument command, Strin
6464
if (NewRelicSecurity.isHookProcessingActive() &&
6565
!NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() && command != null) {
6666
operation = new NoSQLOperation(command.toJson(), typeOfOperation, klassName, methodName);
67+
NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3);
6768
NewRelicSecurity.getAgent().registerOperation(operation);
6869
}
6970
} catch (Throwable e) {

instrumentation-security/mongodb-3.7/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public static AbstractOperation recordMongoOperation(BsonDocument command, Strin
6262
if (NewRelicSecurity.isHookProcessingActive() &&
6363
!NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() && command != null) {
6464
operation = new NoSQLOperation(command.toJson(), typeOfOperation, klassName, methodName);
65+
NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3);
6566
NewRelicSecurity.getAgent().registerOperation(operation);
6667
}
6768
} catch (Throwable e) {

instrumentation-security/mongodb-3.8/src/main/java/com/newrelic/agent/security/instrumentation/mongo/MongoUtil.java

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public static AbstractOperation recordMongoOperation(BsonDocument command, Strin
5252
if (NewRelicSecurity.isHookProcessingActive() &&
5353
!NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty() && command != null) {
5454
operation = new NoSQLOperation(command.toJson(), typeOfOperation, klassName, methodName);
55+
NewRelicSecurity.getAgent().getSecurityMetaData().getMetaData().setFromJumpRequiredInStackTrace(3);
5556
NewRelicSecurity.getAgent().registerOperation(operation);
5657
}
5758
} catch (Throwable e) {

instrumentation-security/solr-4.0.0/build.gradle

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ dependencies {
1414
implementation("org.apache.httpcomponents:httpclient:4.1.3") {
1515
transitive = false
1616
}
17+
18+
testImplementation("org.testcontainers:solr:1.20.1")
19+
testImplementation('org.eclipse.jetty:jetty-client:9.4.46.v20220331')
20+
testImplementation('org.eclipse.jetty.http2:http2-client:9.4.46.v20220331')
21+
testImplementation('org.eclipse.jetty.http2:http2-http-client-transport:9.4.46.v20220331')
22+
testImplementation("org.apache.httpcomponents:httpmime:4.1.3")
23+
testImplementation("org.apache.zookeeper:zookeeper:3.9.2")
24+
testImplementation("org.noggit:noggit:0.8")
1725
}
1826

1927
jar {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
package com.nr.agent.instrumentation.solr4;
2+
3+
import com.newrelic.agent.security.introspec.InstrumentationTestConfig;
4+
import com.newrelic.agent.security.introspec.SecurityInstrumentationTestRunner;
5+
import com.newrelic.api.agent.security.schema.AbstractOperation;
6+
import com.newrelic.api.agent.security.schema.operation.SolrDbOperation;
7+
import org.apache.solr.client.solrj.SolrQuery;
8+
import org.apache.solr.client.solrj.SolrServerException;
9+
import org.apache.solr.client.solrj.impl.HttpSolrServer;
10+
import org.apache.solr.client.solrj.request.UpdateRequest;
11+
import org.apache.solr.common.SolrInputDocument;
12+
import org.junit.AfterClass;
13+
import org.junit.Assert;
14+
import org.junit.BeforeClass;
15+
import org.junit.FixMethodOrder;
16+
import org.junit.Test;
17+
import org.junit.runner.RunWith;
18+
import org.junit.runners.MethodSorters;
19+
import org.testcontainers.containers.GenericContainer;
20+
import org.testcontainers.utility.DockerImageName;
21+
22+
import java.io.IOException;
23+
import java.util.Collections;
24+
import java.util.HashMap;
25+
import java.util.List;
26+
27+
@RunWith(SecurityInstrumentationTestRunner.class)
28+
@InstrumentationTestConfig(includePrefixes = "org.apache.solr")
29+
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
30+
public class SolrTest {
31+
32+
private static GenericContainer<?> solrServer;
33+
34+
private static HttpSolrServer solr;
35+
36+
private static final String CORE = "myCore";
37+
38+
private static String url;
39+
40+
private static final HashMap<String, String> params = new HashMap<>();
41+
42+
@BeforeClass
43+
public static void setup() throws InterruptedException, IOException, SolrServerException {
44+
int PORT = SecurityInstrumentationTestRunner.getIntrospector().getRandomPort();
45+
url = String.format("http://localhost:%s/solr/%s", PORT, CORE);
46+
47+
solrServer = new GenericContainer<>(DockerImageName.parse("solr:8"));
48+
solrServer.setPortBindings(Collections.singletonList(PORT + ":8983"));
49+
solrServer.start();
50+
solrServer.execInContainer("solr", "start");
51+
solrServer.execInContainer("solr", "create", "-c", CORE);
52+
53+
solr = new HttpSolrServer(url);
54+
55+
solr.add(getDocument("ish", 4, "abc"));
56+
solr.add(getDocument("ish", 5, "abc"));
57+
solr.add(getDocument("ish", 6, "abc"));
58+
params.put("waitSearcher", "true");
59+
params.put("commit", "true");
60+
params.put("softCommit", "false");
61+
}
62+
63+
@AfterClass
64+
public static void tearDown() {
65+
if (solrServer != null){
66+
solrServer.stop();
67+
solrServer.close();
68+
}
69+
}
70+
71+
private static SolrInputDocument getDocument(String name, int id, String city) {
72+
SolrInputDocument document = new SolrInputDocument();
73+
document.addField("id", id);
74+
document.addField("name", name);
75+
document.addField("Phone No", Collections.singletonList("9876543210"));
76+
document.addField("City", city);
77+
return document;
78+
}
79+
80+
@Test
81+
public void addDocumentTest() throws SolrServerException, IOException {
82+
SolrInputDocument document = getDocument("Ishi", 1, "Pune");
83+
solr.add(document);
84+
solr.commit();
85+
assertSolrOperation("POST", "/update", document);
86+
}
87+
88+
@Test
89+
public void addMultiDocumentsTest() throws SolrServerException, IOException {
90+
SolrInputDocument document1 = getDocument("Harry", 2, "Hogwarts");
91+
SolrInputDocument document2 = getDocument("Ron", 3, "Mumbai");
92+
solr.add(document1);
93+
solr.add(document2);
94+
solr.commit();
95+
assertSolrOperation("POST", "/update", document1, document2);
96+
}
97+
98+
@Test
99+
public void updateDocument1Test() throws SolrServerException, IOException {
100+
SolrInputDocument document = getDocument("Ron", 3, "Hogwarts");
101+
UpdateRequest request = new UpdateRequest();
102+
request.setAction(UpdateRequest.ACTION.COMMIT, false, true);
103+
request.add(document);
104+
request.process(solr);
105+
assertSolrOperation("POST", "/update", document);
106+
}
107+
108+
@Test
109+
public void updateDocument2Test() throws SolrServerException, IOException {
110+
SolrInputDocument document = getDocument("Ron", 3, "Hogwarts");
111+
UpdateRequest request = new UpdateRequest();
112+
request.setAction(UpdateRequest.ACTION.COMMIT, false, true, false);
113+
request.add(document);
114+
solr.request(request);
115+
assertSolrOperation("POST", "/update", document);
116+
}
117+
118+
@Test
119+
public void deleteDocument1Test() throws SolrServerException, IOException {
120+
solr.deleteById("1");
121+
assertSolrOperation("POST", "/update");
122+
}
123+
124+
@Test
125+
public void deleteDocument2Test() throws SolrServerException, IOException {
126+
UpdateRequest request = new UpdateRequest();
127+
request.deleteById("1");
128+
request.process(solr);
129+
assertSolrOperation("POST", "/update");
130+
}
131+
132+
@Test
133+
public void deleteDocument3Test() throws SolrServerException, IOException {
134+
UpdateRequest request = new UpdateRequest();
135+
request.deleteByQuery("City:abc");
136+
request.process(solr);
137+
assertSolrOperation("POST", "/update");
138+
}
139+
140+
@Test
141+
public void zQueryDataTest() throws SolrServerException, IOException {
142+
SolrQuery query = new SolrQuery();
143+
query.setQuery("*:*");
144+
query.addField("*");
145+
146+
params.clear();
147+
params.put("q", "*:*");
148+
params.put("fl", "*");
149+
150+
solr.query(query);
151+
assertSolrOperation("GET", "/select");
152+
}
153+
154+
@Test
155+
public void zQueryData2Test() throws SolrServerException, IOException {
156+
SolrQuery query = new SolrQuery();
157+
query.set("q", "City:abc");
158+
query.addField("id");
159+
160+
solr.query(query);
161+
params.clear();
162+
params.put("q", "City:abc");
163+
params.put("fl", "id");
164+
assertSolrOperation("GET", "/select");
165+
}
166+
167+
@Test
168+
public void zQueryData3Test() throws SolrServerException, IOException {
169+
SolrQuery query = new SolrQuery();
170+
query.set("q", "id:1");
171+
query.addField("*");
172+
query.addFacetQuery("City");
173+
solr.query(query);
174+
175+
params.clear();
176+
params.put("q", "id:1");
177+
params.put("fl", "*");
178+
params.put("facet", "true");
179+
params.put("facet.query", "City");
180+
assertSolrOperation("GET", "/select");
181+
}
182+
183+
@Test
184+
public void pingTest() throws SolrServerException, IOException {
185+
solr.ping();
186+
assertSolrOperation("GET", "/admin/ping");
187+
}
188+
189+
190+
private void assertSolrOperation(String method, String path, SolrInputDocument... docs){
191+
List<AbstractOperation> operations = SecurityInstrumentationTestRunner.getIntrospector().getOperations();
192+
Assert.assertNotNull(operations);
193+
int i = 0;
194+
Assert.assertFalse(operations.isEmpty());
195+
for (AbstractOperation op : operations) {
196+
Assert.assertTrue(op instanceof SolrDbOperation);
197+
SolrDbOperation operation = (SolrDbOperation) op;
198+
199+
// TODO: discuss collection definition in instrumentation
200+
Assert.assertEquals("solr/"+ CORE, operation.getCollection());
201+
202+
Assert.assertEquals(method, operation.getMethod());
203+
Assert.assertEquals(path, operation.getPath());
204+
Assert.assertEquals(url, operation.getConnectionURL());
205+
if (operation.getDocuments() != null && !operation.getDocuments().isEmpty()) {
206+
Assert.assertEquals(docs[i].size(), ((SolrInputDocument)(operation.getDocuments().get(0))).size());
207+
Assert.assertEquals(docs[i], operation.getDocuments().get(0));
208+
++i;
209+
}
210+
if (operation.getParams() != null && !operation.getParams().isEmpty()) {
211+
Assert.assertEquals(SolrTest.params.size(), operation.getParams().size());
212+
Assert.assertEquals(SolrTest.params, operation.getParams());
213+
}
214+
}
215+
}
216+
}

instrumentation-security/solr-5.0.0/build.gradle

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ dependencies {
1414
implementation("org.apache.httpcomponents:httpclient:4.3.1") {
1515
transitive = false
1616
}
17+
18+
testImplementation("org.testcontainers:solr:1.20.1")
19+
testImplementation('org.eclipse.jetty:jetty-client:9.4.46.v20220331')
20+
testImplementation('org.eclipse.jetty.http2:http2-client:9.4.46.v20220331')
21+
testImplementation('org.eclipse.jetty.http2:http2-http-client-transport:9.4.46.v20220331')
22+
testImplementation("org.apache.httpcomponents:httpmime:4.1.3")
23+
testImplementation("org.apache.zookeeper:zookeeper:3.9.2")
24+
testImplementation("org.noggit:noggit:0.8")
1725
}
1826

1927
jar {

0 commit comments

Comments
 (0)