Skip to content

Commit

Permalink
handle index not exists for detector search and delete (#396)
Browse files Browse the repository at this point in the history
Signed-off-by: Surya Sashank Nistala <[email protected]>
  • Loading branch information
eirsep authored Apr 12, 2023
1 parent 7f5d2c5 commit e50c70a
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.opensearch.securityanalytics.action.DeleteDetectorResponse;
import org.opensearch.securityanalytics.mapper.IndexTemplateManager;
import org.opensearch.securityanalytics.model.Detector;
import org.opensearch.securityanalytics.util.DetectorIndices;
import org.opensearch.securityanalytics.util.RuleTopicIndices;
import org.opensearch.securityanalytics.util.SecurityAnalyticsException;
import org.opensearch.tasks.Task;
Expand All @@ -63,19 +64,22 @@ public class TransportDeleteDetectorAction extends HandledTransportAction<Delete

private final IndexTemplateManager indexTemplateManager;

private final DetectorIndices detectorIndices;

@Inject
public TransportDeleteDetectorAction(TransportService transportService, IndexTemplateManager indexTemplateManager, Client client, ActionFilters actionFilters, NamedXContentRegistry xContentRegistry, RuleTopicIndices ruleTopicIndices) {
public TransportDeleteDetectorAction(TransportService transportService, IndexTemplateManager indexTemplateManager, Client client, ActionFilters actionFilters, NamedXContentRegistry xContentRegistry, RuleTopicIndices ruleTopicIndices, DetectorIndices detectorIndices) {
super(DeleteDetectorAction.NAME, transportService, actionFilters, DeleteDetectorRequest::new);
this.client = client;
this.ruleTopicIndices = ruleTopicIndices;
this.xContentRegistry = xContentRegistry;
this.threadPool = client.threadPool();
this.indexTemplateManager = indexTemplateManager;
this.detectorIndices = detectorIndices;
}

@Override
protected void doExecute(Task task, DeleteDetectorRequest request, ActionListener<DeleteDetectorResponse> listener) {
AsyncDeleteDetectorAction asyncAction = new AsyncDeleteDetectorAction(task, request, listener);
AsyncDeleteDetectorAction asyncAction = new AsyncDeleteDetectorAction(task, request, listener, detectorIndices);
asyncAction.start();
}

Expand All @@ -96,17 +100,31 @@ class AsyncDeleteDetectorAction {
private final ActionListener<DeleteDetectorResponse> listener;
private final AtomicReference<Object> response;
private final AtomicBoolean counter = new AtomicBoolean();
private final DetectorIndices detectorIndices;
private final Task task;

AsyncDeleteDetectorAction(Task task, DeleteDetectorRequest request, ActionListener<DeleteDetectorResponse> listener) {
AsyncDeleteDetectorAction(
Task task,
DeleteDetectorRequest request,
ActionListener<DeleteDetectorResponse> listener,
DetectorIndices detectorIndices) {
this.task = task;
this.request = request;
this.listener = listener;

this.response = new AtomicReference<>();
this.detectorIndices = detectorIndices;
}

void start() {
if (!detectorIndices.detectorIndexExists()) {
onFailures(new OpenSearchStatusException(
String.format(Locale.getDefault(),
"Detector with %s is not found",
request.getDetectorId()),
RestStatus.NOT_FOUND));
return;

}
TransportDeleteDetectorAction.this.threadPool.getThreadContext().stashContext();
String detectorId = request.getDetectorId();
GetRequest getRequest = new GetRequest(Detector.DETECTORS_INDEX, detectorId);
Expand Down Expand Up @@ -204,6 +222,7 @@ private void onOperation(DeleteResponse response) {
}

private void onFailures(Exception t) {
log.error(String.format(Locale.ROOT, "Failed to delete detector"));
if (counter.compareAndSet(false, true)) {
finishHim(null, t);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.apache.lucene.search.TotalHits;
import org.opensearch.OpenSearchStatusException;
import org.opensearch.action.ActionListener;
import org.opensearch.action.search.SearchResponse;

import org.opensearch.action.search.SearchResponseSections;
import org.opensearch.action.search.ShardSearchFailure;
import org.opensearch.action.support.ActionFilters;
import org.opensearch.action.support.HandledTransportAction;
import org.opensearch.commons.authuser.User;
Expand All @@ -20,6 +24,12 @@
import org.opensearch.cluster.service.ClusterService;
import org.opensearch.core.xcontent.NamedXContentRegistry;
import org.opensearch.rest.RestStatus;
import org.opensearch.search.SearchHit;
import org.opensearch.search.SearchHits;
import org.opensearch.search.aggregations.InternalAggregations;
import org.opensearch.search.internal.InternalSearchResponse;
import org.opensearch.search.profile.SearchProfileShardResults;
import org.opensearch.search.suggest.Suggest;
import org.opensearch.securityanalytics.action.SearchDetectorAction;
import org.opensearch.securityanalytics.action.SearchDetectorRequest;
import org.opensearch.securityanalytics.settings.SecurityAnalyticsSettings;
Expand All @@ -30,7 +40,11 @@
import org.opensearch.transport.TransportService;


import java.util.Collections;
import java.util.Locale;

import static org.opensearch.rest.RestStatus.OK;
import static org.opensearch.securityanalytics.util.DetectorUtils.getEmptySearchResponse;

public class TransportSearchDetectorAction extends HandledTransportAction<SearchDetectorRequest, SearchResponse> implements SecureTransportAction {

Expand Down Expand Up @@ -78,7 +92,10 @@ protected void doExecute(Task task, SearchDetectorRequest searchDetectorRequest,
}

this.threadPool.getThreadContext().stashContext();

if (!detectorIndices.detectorIndexExists()) {
actionListener.onResponse(getEmptySearchResponse());
return;
}
client.search(searchDetectorRequest.searchRequest(), new ActionListener<>() {
@Override
public void onResponse(SearchResponse response) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,49 @@
*/
package org.opensearch.securityanalytics.util;

import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.apache.lucene.search.TotalHits;
import org.opensearch.action.ActionListener;
import org.opensearch.action.search.SearchRequest;
import org.opensearch.action.search.SearchResponse;
import org.opensearch.action.search.ShardSearchFailure;
import org.opensearch.client.Client;
import org.opensearch.common.xcontent.LoggingDeprecationHandler;
import org.opensearch.common.xcontent.XContentType;
import org.opensearch.core.xcontent.NamedXContentRegistry;
import org.opensearch.core.xcontent.XContentParser;
import org.opensearch.search.SearchHit;
import org.opensearch.search.SearchHits;
import org.opensearch.search.aggregations.InternalAggregations;
import org.opensearch.search.builder.SearchSourceBuilder;
import org.opensearch.search.fetch.subphase.FetchSourceContext;
import org.opensearch.search.internal.InternalSearchResponse;
import org.opensearch.search.profile.SearchProfileShardResults;
import org.opensearch.search.suggest.Suggest;
import org.opensearch.securityanalytics.model.Detector;
import org.opensearch.securityanalytics.model.DetectorInput;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

public class DetectorUtils {

public static final String DETECTOR_TYPE_PATH = "detector.detector_type";
public static final String DETECTOR_ID_FIELD = "detector_id";

public static SearchResponse getEmptySearchResponse() {
return new SearchResponse(new InternalSearchResponse(
new SearchHits(new SearchHit[0], new TotalHits(0L, TotalHits.Relation.EQUAL_TO), 0.0f),
InternalAggregations.from(Collections.emptyList()),
new Suggest(Collections.emptyList()),
new SearchProfileShardResults(Collections.emptyMap()), false, false, 0),
"", 0, 0, 0, 0,
ShardSearchFailure.EMPTY_ARRAY, SearchResponse.Clusters.EMPTY);
}

public static List<Detector> getDetectors(SearchResponse response, NamedXContentRegistry xContentRegistry) throws IOException {
List<Detector> detectors = new LinkedList<>();
for (SearchHit hit : response.getHits()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,30 @@ public void testCreatingADetector() throws IOException {
Assert.assertEquals(5, noOfSigmaRuleMatches);
}

@SuppressWarnings("unchecked")
public void test_searchDetectors_detectorsIndexNotExists() throws IOException {
try {
makeRequest(client(), "DELETE", SecurityAnalyticsPlugin.DETECTOR_BASE_URI + "/" + "d1", Collections.emptyMap(), null);
fail("delete detector call should have failed");
} catch (IOException e) {
assertTrue(e.getMessage().contains("not found"));
}
String request = "{\n" +
" \"query\" : {\n" +
" \"match_all\":{\n" +
" }\n" +
" }\n" +
"}";
HttpEntity requestEntity = new StringEntity(request, ContentType.APPLICATION_JSON);
Response searchResponse = makeRequest(client(), "POST", SecurityAnalyticsPlugin.DETECTOR_BASE_URI + "/" + "_search", Collections.emptyMap(), requestEntity);
Map<String, Object> searchResponseBody = asMap(searchResponse);
Assert.assertNotNull("response is not null", searchResponseBody);
Map<String, Object> searchResponseHits = (Map) searchResponseBody.get("hits");
Map<String, Object> searchResponseTotal = (Map) searchResponseHits.get("total");
Assert.assertEquals(0, searchResponseTotal.get("value"));
}


public void testCreatingADetectorWithMultipleIndices() throws IOException {
String index1 = createTestIndex("windows-1", windowsIndexMapping());
String index2 = createTestIndex("windows-2", windowsIndexMapping());
Expand Down

0 comments on commit e50c70a

Please sign in to comment.