Skip to content

Commit

Permalink
add guard rail for only one threat intel monitor to exist (opensearch…
Browse files Browse the repository at this point in the history
…-project#1106)

Signed-off-by: Surya Sashank Nistala <[email protected]>
  • Loading branch information
eirsep authored Jun 27, 2024
1 parent ae53139 commit a52b7c1
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.opensearch.OpenSearchStatusException;
import org.opensearch.ResourceAlreadyExistsException;
import org.opensearch.action.search.SearchRequest;
import org.opensearch.action.support.ActionFilters;
import org.opensearch.action.support.HandledTransportAction;
import org.opensearch.action.support.WriteRequest;
Expand All @@ -26,12 +28,19 @@
import org.opensearch.core.common.io.stream.NamedWriteableRegistry;
import org.opensearch.core.rest.RestStatus;
import org.opensearch.core.xcontent.NamedXContentRegistry;
import org.opensearch.index.IndexNotFoundException;
import org.opensearch.index.query.BoolQueryBuilder;
import org.opensearch.index.query.QueryBuilders;
import org.opensearch.index.seqno.SequenceNumbers;
import org.opensearch.rest.RestRequest;
import org.opensearch.search.SearchHit;
import org.opensearch.search.builder.SearchSourceBuilder;
import org.opensearch.securityanalytics.settings.SecurityAnalyticsSettings;
import org.opensearch.securityanalytics.threatIntel.action.monitor.IndexThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.action.monitor.request.IndexThreatIntelMonitorRequest;
import org.opensearch.securityanalytics.threatIntel.action.monitor.request.SearchThreatIntelMonitorRequest;
import org.opensearch.securityanalytics.threatIntel.action.monitor.response.IndexThreatIntelMonitorResponse;
import org.opensearch.securityanalytics.threatIntel.iocscan.service.ThreatIntelMonitorRunner;
import org.opensearch.securityanalytics.threatIntel.model.monitor.PerIocTypeScanInput;
import org.opensearch.securityanalytics.threatIntel.model.monitor.ThreatIntelInput;
import org.opensearch.securityanalytics.threatIntel.sacommons.monitor.ThreatIntelTriggerDto;
Expand All @@ -45,6 +54,7 @@
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
Expand All @@ -55,6 +65,7 @@
public class TransportIndexThreatIntelMonitorAction extends HandledTransportAction<IndexThreatIntelMonitorRequest, IndexThreatIntelMonitorResponse> implements SecureTransportAction {
private static final Logger log = LogManager.getLogger(TransportIndexThreatIntelMonitorAction.class);

private final TransportSearchThreatIntelMonitorAction transportSearchThreatIntelMonitorAction;
private final ThreadPool threadPool;
private final Settings settings;
private final NamedWriteableRegistry namedWriteableRegistry;
Expand All @@ -66,6 +77,7 @@ public class TransportIndexThreatIntelMonitorAction extends HandledTransportActi
@Inject
public TransportIndexThreatIntelMonitorAction(
final TransportService transportService,
final TransportSearchThreatIntelMonitorAction transportSearchThreatIntelMonitorAction,
final ActionFilters actionFilters,
final ThreadPool threadPool,
final Settings settings,
Expand All @@ -74,6 +86,7 @@ public TransportIndexThreatIntelMonitorAction(
final NamedXContentRegistry namedXContentRegistry
) {
super(IndexThreatIntelMonitorAction.NAME, transportService, actionFilters, IndexThreatIntelMonitorRequest::new);
this.transportSearchThreatIntelMonitorAction = transportSearchThreatIntelMonitorAction;
this.threadPool = threadPool;
this.settings = settings;
this.namedWriteableRegistry = namedWriteableRegistry;
Expand All @@ -93,27 +106,62 @@ protected void doExecute(Task task, IndexThreatIntelMonitorRequest request, Acti
listener.onFailure(SecurityAnalyticsException.wrap(new OpenSearchStatusException(validateBackendRoleMessage, RestStatus.FORBIDDEN)));
return;
}
//fetch monitors and search
SearchRequest threatIntelMonitorsSearchRequest = new SearchRequest();
threatIntelMonitorsSearchRequest.indices(".opendistro-alerting-config");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.should().add(new BoolQueryBuilder().must(QueryBuilders.matchQuery("monitor.owner", PLUGIN_OWNER_FIELD)));
boolQueryBuilder.should().add(new BoolQueryBuilder().must(QueryBuilders.matchQuery("monitor.monitor_type", ThreatIntelMonitorRunner.THREAT_INTEL_MONITOR_TYPE)));
threatIntelMonitorsSearchRequest.source(new SearchSourceBuilder().query(boolQueryBuilder));
transportSearchThreatIntelMonitorAction.execute(new SearchThreatIntelMonitorRequest(threatIntelMonitorsSearchRequest), ActionListener.wrap(
searchResponse -> {
List<String> monitorIds = searchResponse.getHits() == null || searchResponse.getHits().getHits() == null ? new ArrayList<>() :
Arrays.stream(searchResponse.getHits().getHits()).map(SearchHit::getId).collect(Collectors.toList());
if (monitorIds.isEmpty()) {
createMonitor(request, listener, user);
} else
listener.onFailure(new ResourceAlreadyExistsException(String.format("Threat intel monitor %s already exists.", monitorIds.get(0))));
},

IndexMonitorRequest indexMonitorRequest = buildIndexMonitorRequest(request);
AlertingPluginInterface.INSTANCE.indexMonitor((NodeClient) client, indexMonitorRequest, namedWriteableRegistry, ActionListener.wrap(
r -> {
log.debug(
"{} threat intel monitor {}", request.getMethod() == RestRequest.Method.PUT ? "Updated" : "Created",
r.getId()
);
IndexThreatIntelMonitorResponse response = getIndexThreatIntelMonitorResponse(r, user);
listener.onResponse(response);
}, e -> {
log.error("failed to creat threat intel monitor", e);
listener.onFailure(new SecurityAnalyticsException("Failed to create threat intel monitor", RestStatus.INTERNAL_SERVER_ERROR, e));
e -> {
if (e instanceof IndexNotFoundException || e.getMessage().contains("Configured indices are not found")) {
try {
createMonitor(request, listener, user);
return;
} catch (IOException ex) {
log.error(() -> new ParameterizedMessage("Unexpected failure while indexing threat intel monitor {} named {}", request.getId(), request.getMonitor().getName()));
listener.onFailure(new SecurityAnalyticsException("Unexpected failure while indexing threat intel monitor", RestStatus.INTERNAL_SERVER_ERROR, e));
return;
}
}
log.error("Failed to update threat intel monitor alerts status", e);
listener.onFailure(e);
}
));

} catch (Exception e) {
log.error(() -> new ParameterizedMessage("Unexpected failure while indexing threat intel monitor {} named {}", request.getId(), request.getMonitor().getName()));
listener.onFailure(new SecurityAnalyticsException("Unexpected failure while indexing threat intel monitor", RestStatus.INTERNAL_SERVER_ERROR, e));
}
}

private void createMonitor(IndexThreatIntelMonitorRequest request, ActionListener<IndexThreatIntelMonitorResponse> listener, User user) throws IOException {
IndexMonitorRequest indexMonitorRequest = buildIndexMonitorRequest(request);
AlertingPluginInterface.INSTANCE.indexMonitor((NodeClient) client, indexMonitorRequest, namedWriteableRegistry, ActionListener.wrap(
r -> {
log.debug(
"{} threat intel monitor {}", request.getMethod() == RestRequest.Method.PUT ? "Updated" : "Created",
r.getId()
);
IndexThreatIntelMonitorResponse response = getIndexThreatIntelMonitorResponse(r, user);
listener.onResponse(response);
}, e -> {
log.error("failed to creat threat intel monitor", e);
listener.onFailure(new SecurityAnalyticsException("Failed to create threat intel monitor", RestStatus.INTERNAL_SERVER_ERROR, e));
}
));
}

private IndexThreatIntelMonitorResponse getIndexThreatIntelMonitorResponse(IndexMonitorResponse r, User user) throws IOException {
IndexThreatIntelMonitorResponse response = new IndexThreatIntelMonitorResponse(r.getId(), r.getVersion(), r.getSeqNo(), r.getPrimaryTerm(),
ThreatIntelMonitorUtils.buildThreatIntelMonitorDto(r.getId(), r.getMonitor(), xContentRegistry));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,21 @@ public void testCreateThreatIntelMonitor() throws IOException {
String index = createTestIndex(randomIndex(), windowsIndexMapping());
String monitorName = "test_monitor_name";


/**create monitor */
ThreatIntelMonitorDto iocScanMonitor = randomIocScanMonitorDto(index);
Response response = makeRequest(client(), "POST", SecurityAnalyticsPlugin.THREAT_INTEL_MONITOR_URI, Collections.emptyMap(), toHttpEntity(iocScanMonitor));
Assert.assertEquals(201, response.getStatusLine().getStatusCode());
Map<String, Object> responseBody = asMap(response);

try {
makeRequest(client(), "POST", SecurityAnalyticsPlugin.THREAT_INTEL_MONITOR_URI, Collections.emptyMap(), toHttpEntity(iocScanMonitor));
fail();
} catch (Exception e) {
/** creating a second threat intel monitor should fail*/
assertTrue(e.getMessage().contains("already exists"));
}

final String monitorId = responseBody.get("id").toString();
Assert.assertNotEquals("response is missing Id", Monitor.NO_ID, monitorId);

Expand Down

0 comments on commit a52b7c1

Please sign in to comment.