Skip to content
Open
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import org.opensearch.gradle.testclusters.OpenSearchCluster

buildscript {
ext {
opensearch_version = System.getProperty("opensearch.version", "3.5.0-SNAPSHOT")
opensearch_version = System.getProperty("opensearch.version", "3.6.1-SNAPSHOT")
isSnapshot = "true" == System.getProperty("build.snapshot", "true")
buildVersionQualifier = System.getProperty("build.version_qualifier", "")
version_tokens = opensearch_version.tokenize('-')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## Version 3.5.0 Release Notes

Compatible with OpenSearch and OpenSearch Dashboards version 3.5.0

### Enhancements

* Include AdditionalCodecs argument to allow additional Codec registration ([#1636](https://github.com/opensearch-project/security-analytics/pull/1636))

### Maintenance

* Upgrade SA Commons JAR to netty 4.1.30.Final ([#1638](https://github.com/opensearch-project/security-analytics/pull/1638))
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Version 3.6.0 Release Notes

Compatible with OpenSearch and OpenSearch Dashboards version 3.6.0

### Bug Fixes

* Fix failure when deleting a detector with no associated rules due to empty monitor ID list ([#1648](https://github.com/opensearch-project/security-analytics/pull/1648))

### Maintenance

* Update security-analytics-commons jar to address CVE-2025-67735 ([#1653](https://github.com/opensearch-project/security-analytics/pull/1653))
* Update security-analytics-commons jar to address CVE-2026-33871 and CVE-2026-33870 ([#1685](https://github.com/opensearch-project/security-analytics/pull/1685))
Binary file modified security-analytics-commons-1.0.0.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class CorrelationCodecService extends CodecService {
private final MapperService mapperService;

public CorrelationCodecService(CodecServiceConfig codecServiceConfig, IndexSettings indexSettings) {
super(codecServiceConfig.getMapperService(), indexSettings, codecServiceConfig.getLogger());
super(codecServiceConfig.getMapperService(), indexSettings, codecServiceConfig.getLogger(), codecServiceConfig.getAdditionalCodecs());
mapperService = codecServiceConfig.getMapperService();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,13 @@ private void onGetResponse(Detector detector) {
deleteWorkflow(detector, onDeleteWorkflowStep);
onDeleteWorkflowStep.whenComplete(acknowledgedResponse -> {
List<String> monitorIds = detector.getMonitorIds();

// A detector with 0 rules will have 0 monitors to delete. Skipping monitor deletion steps.
if (monitorIds.isEmpty()) {
deleteDetectorFromConfig(detector.getId(), request.getRefreshPolicy());
return;
}

ActionListener<DeleteMonitorResponse> deletesListener = new GroupedActionListener<>(new ActionListener<>() {
@Override
public void onResponse(Collection<DeleteMonitorResponse> responses) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1877,4 +1877,32 @@ public void testCreatingDetectorWithDynamicQueryIndexEnabledAndThenDisabled() th
Assert.assertEquals("Create detector failed", RestStatus.CREATED, restStatus(createResponse));
Assert.assertTrue(doesIndexExist(DetectorMonitorConfig.getRuleIndex(randomDetectorType()) + "-000001"));
}

public void testDeletingDetectorEditedToHaveZeroRules() throws IOException {
String index = createTestIndex(randomIndex(), windowsIndexMapping());

Request createMappingRequest = new Request("POST", SecurityAnalyticsPlugin.MAPPER_BASE_URI);
createMappingRequest.setJsonEntity(
"{ \"index_name\":\"" + index + "\"," +
" \"rule_topic\":\"" + randomDetectorType() + "\", " +
" \"partial\":true" +
"}"
);
Response response = client().performRequest(createMappingRequest);
assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());

// Create a test detector that has at least 1 rule.
Detector detector = randomDetectorWithTriggers(getRandomPrePackagedRules(), List.of(new DetectorTrigger(null, "test-trigger", "1", List.of(randomDetectorType()), List.of(), List.of(), List.of(), List.of(), List.of())));
String detectorId = createDetector(detector);

// Update the detector to have 0 rules. This should update the detector's 'monitor_id' attribute to be an empty array.
DetectorInput input = new DetectorInput("detector with no rules", List.of(index), List.of(), List.of());
Detector updatedDetector = randomDetectorWithInputs(List.of(input));

Response updateResponse = makeRequest(client(), "PUT", SecurityAnalyticsPlugin.DETECTOR_BASE_URI + "/" + detectorId, Collections.emptyMap(), toHttpEntity(updatedDetector));
Assert.assertEquals("Update detector failed", RestStatus.OK, restStatus(updateResponse));

Response deleteResponse = makeRequest(client(), "DELETE", SecurityAnalyticsPlugin.DETECTOR_BASE_URI + "/" + detectorId, Collections.emptyMap(), null);
Assert.assertEquals("Delete detector failed", RestStatus.OK, restStatus(deleteResponse));
}
}
Loading