Skip to content

Commit

Permalink
search threat intel monitor api
Browse files Browse the repository at this point in the history
Signed-off-by: Surya Sashank Nistala <[email protected]>
  • Loading branch information
eirsep committed Jun 6, 2024
1 parent 63dd56c commit 874d69b
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,15 @@
import org.opensearch.securityanalytics.threatIntel.action.SAGetTIFSourceConfigAction;
import org.opensearch.securityanalytics.threatIntel.action.SAIndexTIFSourceConfigAction;
import org.opensearch.securityanalytics.threatIntel.action.monitor.IndexThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.action.monitor.SearchThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.common.TIFLockService;
import org.opensearch.securityanalytics.threatIntel.feedMetadata.BuiltInTIFMetadataLoader;
import org.opensearch.securityanalytics.threatIntel.jobscheduler.TIFJobRunner;
import org.opensearch.securityanalytics.threatIntel.model.SATIFSourceConfig;
import org.opensearch.securityanalytics.threatIntel.resthandler.RestGetTIFSourceConfigAction;
import org.opensearch.securityanalytics.threatIntel.resthandler.RestIndexTIFSourceConfigAction;
import org.opensearch.securityanalytics.threatIntel.resthandler.monitor.RestIndexIocScanMonitorAction;
import org.opensearch.securityanalytics.threatIntel.resthandler.monitor.RestIndexThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.resthandler.monitor.RestSearchThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.service.DetectorThreatIntelService;
import org.opensearch.securityanalytics.threatIntel.service.SATIFSourceConfigManagementService;
import org.opensearch.securityanalytics.threatIntel.service.SATIFSourceConfigService;
Expand All @@ -131,6 +133,7 @@
import org.opensearch.securityanalytics.threatIntel.transport.TransportIndexTIFSourceConfigAction;
import org.opensearch.securityanalytics.threatIntel.transport.TransportPutTIFJobAction;
import org.opensearch.securityanalytics.threatIntel.transport.monitor.TransportIndexThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.transport.monitor.TransportSearchThreatIntelMonitorAction;
import org.opensearch.securityanalytics.transport.TransportAcknowledgeAlertsAction;
import org.opensearch.securityanalytics.transport.TransportCorrelateFindingAction;
import org.opensearch.securityanalytics.transport.TransportCreateIndexMappingsAction;
Expand Down Expand Up @@ -319,7 +322,8 @@ public List<RestHandler> getRestHandlers(Settings settings,
new RestDeleteCustomLogTypeAction(),
new RestIndexTIFSourceConfigAction(),
new RestGetTIFSourceConfigAction(),
new RestIndexIocScanMonitorAction()
new RestIndexThreatIntelMonitorAction(),
new RestSearchThreatIntelMonitorAction()
);
}

Expand Down Expand Up @@ -456,6 +460,7 @@ public List<Setting<?>> getSettings() {
new ActionHandler<>(DeleteCustomLogTypeAction.INSTANCE, TransportDeleteCustomLogTypeAction.class),
new ActionHandler<>(PutTIFJobAction.INSTANCE, TransportPutTIFJobAction.class),
new ActionHandler<>(IndexThreatIntelMonitorAction.INSTANCE, TransportIndexThreatIntelMonitorAction.class),
new ActionHandler<>(SearchThreatIntelMonitorAction.INSTANCE, TransportSearchThreatIntelMonitorAction.class),
new ActionHandler<>(SAIndexTIFSourceConfigAction.INSTANCE, TransportIndexTIFSourceConfigAction.class),
new ActionHandler<>(SAGetTIFSourceConfigAction.INSTANCE, TransportGetTIFSourceConfigAction.class)
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.opensearch.securityanalytics.threatIntel.action.monitor;

import org.opensearch.action.ActionType;
import org.opensearch.action.search.SearchResponse;
import org.opensearch.securityanalytics.threatIntel.sacommons.monitor.ThreatIntelMonitorActions;

public class SearchThreatIntelMonitorAction extends ActionType<SearchResponse> {

public static final SearchThreatIntelMonitorAction INSTANCE = new SearchThreatIntelMonitorAction();
public static final String NAME = ThreatIntelMonitorActions.SEARCH_THREAT_INTEL_MONITOR_ACTION_NAME;

private SearchThreatIntelMonitorAction() {
super(NAME, SearchResponse::new);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.opensearch.securityanalytics.threatIntel.action.monitor.request;

import org.opensearch.action.ActionRequest;
import org.opensearch.action.ActionRequestValidationException;
import org.opensearch.action.search.SearchRequest;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.io.stream.StreamOutput;

import java.io.IOException;

public class SearchThreatIntelMonitorRequest extends ActionRequest {
private SearchRequest searchRequest;

public SearchThreatIntelMonitorRequest(SearchRequest searchRequest) {
super();
this.searchRequest = searchRequest;
}

public SearchThreatIntelMonitorRequest(StreamInput sin) throws IOException {
searchRequest = new SearchRequest(sin);
}

@Override
public ActionRequestValidationException validate() {
return null;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
searchRequest.writeTo(out);
}

public SearchRequest searchRequest() {
return this.searchRequest;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
import java.util.List;
import java.util.Locale;

public class RestIndexIocScanMonitorAction extends BaseRestHandler {
public class RestIndexThreatIntelMonitorAction extends BaseRestHandler {

private static final Logger log = LogManager.getLogger(RestIndexIocScanMonitorAction.class);
private static final Logger log = LogManager.getLogger(RestIndexThreatIntelMonitorAction.class);

@Override
public String getName() {
return "index_ioc_scan_monitor_action";
return "index_threat_intel_monitor_action";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package org.opensearch.securityanalytics.threatIntel.resthandler.monitor;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.action.search.SearchRequest;
import org.opensearch.action.search.SearchResponse;
import org.opensearch.client.node.NodeClient;
import org.opensearch.cluster.routing.Preference;
import org.opensearch.core.xcontent.ToXContent;
import org.opensearch.index.query.BoolQueryBuilder;
import org.opensearch.index.query.QueryBuilders;
import org.opensearch.rest.BaseRestHandler;
import org.opensearch.rest.BytesRestResponse;
import org.opensearch.rest.RestChannel;
import org.opensearch.rest.RestRequest;
import org.opensearch.rest.RestResponse;
import org.opensearch.rest.action.RestResponseListener;
import org.opensearch.search.builder.SearchSourceBuilder;
import org.opensearch.search.fetch.subphase.FetchSourceContext;
import org.opensearch.securityanalytics.SecurityAnalyticsPlugin;
import org.opensearch.securityanalytics.threatIntel.action.monitor.SearchThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.action.monitor.request.SearchThreatIntelMonitorRequest;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import static org.opensearch.core.rest.RestStatus.OK;
import static org.opensearch.securityanalytics.transport.TransportIndexDetectorAction.PLUGIN_OWNER_FIELD;

public class RestSearchThreatIntelMonitorAction extends BaseRestHandler {
private static final Logger log = LogManager.getLogger(RestSearchThreatIntelMonitorAction.class);
public static final String SEARCH_THREAT_INTEL_MONITOR_PATH = SecurityAnalyticsPlugin.THREAT_INTEL_MONITOR_URI + "/" + "_search";

@Override
public String getName() {
return "search_threat_intel_monitor_action";
}

@Override
public List<Route> routes() {
return List.of(
new Route(RestRequest.Method.POST, SEARCH_THREAT_INTEL_MONITOR_PATH));
}

@Override
protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
log.debug(String.format(Locale.getDefault(), "%s %s", request.method(), SecurityAnalyticsPlugin.THREAT_INTEL_MONITOR_URI + "/" + "_search"));

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.parseXContent(request.contentOrSourceParamParser());
searchSourceBuilder.fetchSource(FetchSourceContext.parseFromRestRequest(request));
searchSourceBuilder.seqNoAndPrimaryTerm(true);
searchSourceBuilder.version(true);

SearchRequest searchRequest = new SearchRequest();
searchRequest.source(searchSourceBuilder);
searchRequest.indices(".opendistro-alerting-config");//todo figure out why it should be mentioned here
searchRequest.preference(Preference.PRIMARY_FIRST.type());

BoolQueryBuilder boolQueryBuilder;

if (searchRequest.source().query() == null) {
boolQueryBuilder = new BoolQueryBuilder();
} else {
boolQueryBuilder = QueryBuilders.boolQuery().must(searchRequest.source().query());
}

BoolQueryBuilder bqb = new BoolQueryBuilder();
bqb.should().add(new BoolQueryBuilder().must(QueryBuilders.matchQuery("monitor.owner", PLUGIN_OWNER_FIELD)));

boolQueryBuilder.filter(bqb);
searchRequest.source().query(boolQueryBuilder);

SearchThreatIntelMonitorRequest searchThreatIntelMonitorRequest = new SearchThreatIntelMonitorRequest(searchRequest);

return channel -> {
client.execute(SearchThreatIntelMonitorAction.INSTANCE, searchThreatIntelMonitorRequest, new RestSearchThreatIntelMonitorResponseListener(channel, request));
};
}

static class RestSearchThreatIntelMonitorResponseListener extends RestResponseListener<SearchResponse> {
private final RestRequest request;

RestSearchThreatIntelMonitorResponseListener(RestChannel channel, RestRequest request) {
super(channel);
this.request = request;
}

@Override
public RestResponse buildResponse(final SearchResponse response) throws Exception {
return new BytesRestResponse(OK, response.toXContent(channel.newBuilder(), ToXContent.EMPTY_PARAMS));
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

public class ThreatIntelMonitorActions {
public static final String INDEX_THREAT_INTEL_MONITOR_ACTION_NAME = "cluster:admin/security_analytics/threatIntel/monitor/write";
public static final String GET_THREAT_INTEL_MONITOR_ACTION_NAME = "cluster:admin/security_analytics/threatIntel/monitor/get";
public static final String SEARCH_THREAT_INTEL_MONITOR_ACTION_NAME = "cluster:admin/security_analytics/threatIntel/monitor/search";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.opensearch.securityanalytics.threatIntel.transport.monitor;

import org.opensearch.action.search.SearchResponse;
import org.opensearch.action.support.ActionFilters;
import org.opensearch.action.support.HandledTransportAction;
import org.opensearch.client.Client;
import org.opensearch.client.node.NodeClient;
import org.opensearch.cluster.service.ClusterService;
import org.opensearch.common.inject.Inject;
import org.opensearch.common.settings.Settings;
import org.opensearch.commons.alerting.AlertingPluginInterface;
import org.opensearch.commons.alerting.action.SearchMonitorRequest;
import org.opensearch.commons.authuser.User;
import org.opensearch.core.action.ActionListener;
import org.opensearch.core.xcontent.NamedXContentRegistry;
import org.opensearch.securityanalytics.settings.SecurityAnalyticsSettings;
import org.opensearch.securityanalytics.threatIntel.action.monitor.SearchThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.action.monitor.request.SearchThreatIntelMonitorRequest;
import org.opensearch.securityanalytics.transport.SecureTransportAction;
import org.opensearch.tasks.Task;
import org.opensearch.threadpool.ThreadPool;
import org.opensearch.transport.TransportService;

public class TransportSearchThreatIntelMonitorAction extends HandledTransportAction<SearchThreatIntelMonitorRequest, SearchResponse> implements SecureTransportAction {

private final NamedXContentRegistry xContentRegistry;
private final Client client;
private final ClusterService clusterService;
private final Settings settings;
private final ThreadPool threadPool;
private Boolean filterByEnabled;

@Inject
public TransportSearchThreatIntelMonitorAction(TransportService transportService,
ClusterService clusterService,
ActionFilters actionFilters,
NamedXContentRegistry xContentRegistry,
Settings settings,
Client client,
ThreadPool threadPool) {
super(SearchThreatIntelMonitorAction.NAME, transportService, actionFilters, SearchThreatIntelMonitorRequest::new);
this.xContentRegistry = xContentRegistry;
this.client = client;
this.clusterService = clusterService;
this.settings = settings;
this.threadPool = threadPool;
this.filterByEnabled = SecurityAnalyticsSettings.FILTER_BY_BACKEND_ROLES.get(this.settings);
this.clusterService.getClusterSettings().addSettingsUpdateConsumer(SecurityAnalyticsSettings.FILTER_BY_BACKEND_ROLES, this::setFilterByEnabled);
}

@Override
protected void doExecute(Task task, SearchThreatIntelMonitorRequest request, ActionListener<SearchResponse> listener) {
User user = readUserFromThreadContext(this.threadPool);

// if (doFilterForUser(user, this.filterByEnabled)) {
// // security is enabled and filterby is enabled
// log.info("Filtering result by: {}", user.getBackendRoles());
// addFilter(user, request.searchRequest().source(), "detector.user.backend_roles.keyword");
// } // TODO

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

//TODO change search request to fetch threat intel monitors
AlertingPluginInterface.INSTANCE.searchMonitors((NodeClient) client, new SearchMonitorRequest(request.searchRequest()), listener);
}


private void setFilterByEnabled(boolean filterByEnabled) {
this.filterByEnabled = filterByEnabled;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.opensearch.securityanalytics.resthandler;

import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Assert;
Expand All @@ -15,9 +17,12 @@
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.opensearch.securityanalytics.threatIntel.resthandler.monitor.RestSearchThreatIntelMonitorAction.SEARCH_THREAT_INTEL_MONITOR_PATH;

public class ThreatIntelMonitorRestApiIT extends SecurityAnalyticsRestTestCase {
private static final Logger log = LogManager.getLogger(ThreatIntelMonitorRestApiIT.class);

Expand All @@ -35,6 +40,20 @@ public void testCreateThreatIntelMonitor() throws IOException {

Response alertingMonitorResponse = getAlertingMonitor(client(), createdId);
Assert.assertEquals(200, alertingMonitorResponse.getStatusLine().getStatusCode());

String matchAllRequest = "{\n" +
" \"query\" : {\n" +
" \"match_all\":{\n" +
" }\n" +
" }\n" +
"}";
Response searchMonitorResponse = makeRequest(client(), "POST", SEARCH_THREAT_INTEL_MONITOR_PATH, Collections.emptyMap(), new StringEntity(matchAllRequest, ContentType.APPLICATION_JSON, false));
Assert.assertEquals(200, alertingMonitorResponse.getStatusLine().getStatusCode());
HashMap<String, Object> hits = (HashMap<String, Object>) asMap(searchMonitorResponse).get("hits");
HashMap<String, Object> totalHits = (HashMap<String, Object>) hits.get("total");
Integer totalHitsVal = (Integer) totalHits.get("value");
assertEquals(totalHitsVal.intValue(), 1);

}

private ThreatIntelMonitorDto randomIocScanMonitorDto() {
Expand Down

0 comments on commit 874d69b

Please sign in to comment.