Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Threat intel monitor implementation #1092

Merged
merged 15 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
import org.opensearch.securityanalytics.threatIntel.action.SARefreshTIFSourceConfigAction;
import org.opensearch.securityanalytics.threatIntel.action.SASearchTIFSourceConfigsAction;
import org.opensearch.securityanalytics.threatIntel.action.monitor.DeleteThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.action.monitor.GetThreatIntelAlertsAction;
import org.opensearch.securityanalytics.threatIntel.action.monitor.IndexThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.action.monitor.SearchThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.common.TIFLockService;
Expand All @@ -151,6 +152,7 @@
import org.opensearch.securityanalytics.threatIntel.resthandler.RestRefreshTIFSourceConfigAction;
import org.opensearch.securityanalytics.threatIntel.resthandler.RestSearchTIFSourceConfigsAction;
import org.opensearch.securityanalytics.threatIntel.resthandler.monitor.RestDeleteThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.resthandler.monitor.RestGetThreatIntelAlertsAction;
import org.opensearch.securityanalytics.threatIntel.resthandler.monitor.RestIndexThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.resthandler.monitor.RestSearchThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.service.DetectorThreatIntelService;
Expand All @@ -167,6 +169,7 @@
import org.opensearch.securityanalytics.threatIntel.transport.TransportRefreshTIFSourceConfigAction;
import org.opensearch.securityanalytics.threatIntel.transport.TransportSearchTIFSourceConfigsAction;
import org.opensearch.securityanalytics.threatIntel.transport.monitor.TransportDeleteThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.transport.monitor.TransportGetThreatIntelAlertsAction;
import org.opensearch.securityanalytics.threatIntel.transport.monitor.TransportIndexThreatIntelMonitorAction;
import org.opensearch.securityanalytics.threatIntel.transport.monitor.TransportSearchThreatIntelMonitorAction;
import org.opensearch.securityanalytics.transport.TransportAckCorrelationAlertsAction;
Expand Down Expand Up @@ -234,10 +237,10 @@ public class SecurityAnalyticsPlugin extends Plugin implements ActionPlugin, Map
public static final String LIST_CORRELATIONS_URI = PLUGINS_BASE_URI + "/correlations";
public static final String CORRELATION_RULES_BASE_URI = PLUGINS_BASE_URI + "/correlation/rules";
public static final String THREAT_INTEL_BASE_URI = PLUGINS_BASE_URI + "/threat_intel";
public static final String THREAT_INTEL_SOURCE_URI = PLUGINS_BASE_URI + "/threat_intel/source";
public static final String THREAT_INTEL_MONITOR_URI = PLUGINS_BASE_URI + "/threat_intel/monitor";
public static final String IOCS_URI = PLUGINS_BASE_URI + "/iocs";
public static final String LIST_IOCS_URI = IOCS_URI + "/list";
public static final String THREAT_INTEL_SOURCE_URI = PLUGINS_BASE_URI + "/threat_intel/sources";
public static final String THREAT_INTEL_MONITOR_URI = PLUGINS_BASE_URI + "/threat_intel/monitors";
public static final String LIST_IOCS_URI = PLUGINS_BASE_URI + "/threat_intel/iocs";
public static final String THREAT_INTEL_ALERTS_URI = PLUGINS_BASE_URI + "/threat_intel/alerts";
public static final String TEST_CONNECTION_BASE_URI = PLUGINS_BASE_URI + "/connections/%s/test";
public static final String TEST_S3_CONNECTION_URI = String.format(TEST_CONNECTION_BASE_URI, "s3");

Expand Down Expand Up @@ -320,7 +323,7 @@ public Collection<Object> createComponents(Client client,
ThreatIntelAlertService threatIntelAlertService = new ThreatIntelAlertService(client, clusterService, xContentRegistry);
SaIoCScanService ioCScanService = new SaIoCScanService(client, xContentRegistry, iocFindingService, threatIntelAlertService, notificationService);
return List.of(
detectorIndices, correlationIndices, correlationRuleIndices, ruleTopicIndices, customLogTypeIndices, ruleIndices,
detectorIndices, correlationIndices, correlationRuleIndices, ruleTopicIndices, customLogTypeIndices, ruleIndices,threatIntelAlertService,
mapperService, indexTemplateManager, builtinLogTypeLoader, builtInTIFMetadataLoader, threatIntelFeedDataService, detectorThreatIntelService,
correlationAlertService, notificationService,
tifJobUpdateService, tifJobParameterService, threatIntelLockService, saTifSourceConfigService, saTifSourceConfigManagementService, stix2IOCFetchService,
Expand Down Expand Up @@ -352,6 +355,7 @@ public List<RestHandler> getRestHandlers(Settings settings,
new RestGetFindingsAction(),
new RestGetMappingsViewAction(),
new RestGetAlertsAction(),
new RestGetThreatIntelAlertsAction(),
new RestIndexRuleAction(),
new RestSearchRuleAction(),
new RestDeleteRuleAction(),
Expand Down Expand Up @@ -517,6 +521,7 @@ public List<Setting<?>> getSettings() {
new ActionPlugin.ActionHandler<>(AlertingActions.SUBSCRIBE_FINDINGS_ACTION_TYPE, TransportCorrelateFindingAction.class),
new ActionPlugin.ActionHandler<>(ListCorrelationsAction.INSTANCE, TransportListCorrelationAction.class),
new ActionPlugin.ActionHandler<>(SearchCorrelationRuleAction.INSTANCE, TransportSearchCorrelationRuleAction.class),
new ActionPlugin.ActionHandler<>(GetThreatIntelAlertsAction.INSTANCE, TransportGetThreatIntelAlertsAction.class),
new ActionHandler<>(IndexCustomLogTypeAction.INSTANCE, TransportIndexCustomLogTypeAction.class),
new ActionHandler<>(SearchCustomLogTypeAction.INSTANCE, TransportSearchCustomLogTypeAction.class),
new ActionHandler<>(DeleteCustomLogTypeAction.INSTANCE, TransportDeleteCustomLogTypeAction.class),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ public class GetAlertsAction extends ActionType<GetAlertsResponse> {
public GetAlertsAction() {
super(NAME, GetAlertsResponse::new);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ public class ThreatIntelAlert extends BaseEntity {
public static final String SCHEMA_VERSION_FIELD = "schema_version";
public static final String ALERT_VERSION_FIELD = "version";
public static final String USER_FIELD = "user";
public static final String TRIGGER_NAME_FIELD = "trigger_id";
public static final String TRIGGER_ID_FIELD = "trigger_name";
public static final String TRIGGER_NAME_FIELD = "trigger_name";
public static final String TRIGGER_ID_FIELD = "trigger_id";
public static final String MONITOR_ID_FIELD = "monitor_id";
public static final String MONITOR_NAME_FIELD = "monitor_name";
public static final String STATE_FIELD = "state";
public static final String START_TIME_FIELD = "start_time";
public static final String END_TIME_FIELD = "end_time";
Expand All @@ -48,6 +50,8 @@ public class ThreatIntelAlert extends BaseEntity {
private final User user;
private final String triggerName;
private final String triggerId;
private final String monitorId;
private final String monitorName;
private final Alert.State state;
private final Instant startTime;
private final Instant endTime;
Expand All @@ -67,6 +71,8 @@ public ThreatIntelAlert(
User user,
String triggerId,
String triggerName,
String monitorId,
String monitorName,
Alert.State state,
Instant startTime,
Instant endTime,
Expand All @@ -86,6 +92,8 @@ public ThreatIntelAlert(
this.user = user;
this.triggerId = triggerId;
this.triggerName = triggerName;
this.monitorId = monitorId;
this.monitorName = monitorName;
this.state = state;
this.startTime = startTime;
this.endTime = endTime;
Expand All @@ -106,6 +114,8 @@ public ThreatIntelAlert(StreamInput sin) throws IOException {
this.user = sin.readBoolean() ? new User(sin) : null;
this.triggerId = sin.readString();
this.triggerName = sin.readString();
this.monitorId = sin.readString();
this.monitorName = sin.readString();
this.state = sin.readEnum(Alert.State.class);
this.startTime = sin.readInstant();
this.endTime = sin.readOptionalInstant();
Expand All @@ -127,6 +137,8 @@ public ThreatIntelAlert(ThreatIntelAlert currentAlert, List<String> findingIds)
this.user = currentAlert.user;
this.triggerId = currentAlert.triggerId;
this.triggerName = currentAlert.triggerName;
this.monitorId = currentAlert.monitorId;
this.monitorName = currentAlert.monitorName;
this.state = currentAlert.state;
this.startTime = currentAlert.startTime;
this.endTime = currentAlert.endTime;
Expand Down Expand Up @@ -154,6 +166,8 @@ public void writeTo(StreamOutput out) throws IOException {
}
out.writeString(triggerId);
out.writeString(triggerName);
out.writeString(monitorId);
out.writeString(monitorName);
out.writeEnum(state);
out.writeInstant(startTime);
out.writeOptionalInstant(endTime);
Expand All @@ -173,6 +187,8 @@ public static ThreatIntelAlert parse(XContentParser xcp, long version) throws IO
User user = null;
String triggerId = null;
String triggerName = null;
String monitorId = null;
String monitorName = null;
Alert.State state = null;
Instant startTime = null;
String severity = null;
Expand Down Expand Up @@ -213,6 +229,12 @@ public static ThreatIntelAlert parse(XContentParser xcp, long version) throws IO
case TRIGGER_NAME_FIELD:
triggerName = xcp.text();
break;
case MONITOR_ID_FIELD:
monitorId = xcp.text();
break;
case MONITOR_NAME_FIELD:
monitorName = xcp.text();
break;
case STATE_FIELD:
state = Alert.State.valueOf(xcp.text());
break;
Expand Down Expand Up @@ -256,6 +278,8 @@ public static ThreatIntelAlert parse(XContentParser xcp, long version) throws IO
user,
triggerId,
triggerName,
monitorId,
monitorName,
state,
startTime,
endTime,
Expand Down Expand Up @@ -290,7 +314,9 @@ private XContentBuilder createXContentBuilder(XContentBuilder builder, boolean s
.field(ALERT_VERSION_FIELD, version)
.field(SCHEMA_VERSION_FIELD, schemaVersion)
.field(TRIGGER_NAME_FIELD, triggerName)
.field(TRIGGER_ID_FIELD, triggerName)
.field(TRIGGER_ID_FIELD, triggerId)
.field(MONITOR_ID_FIELD, monitorId)
.field(MONITOR_NAME_FIELD, monitorName)
.field(STATE_FIELD, state)
.field(ERROR_MESSAGE_FIELD, errorMessage)
.field(IOC_VALUE_FIELD, iocValue)
Expand Down Expand Up @@ -395,8 +421,11 @@ public List<String> getFindingIds() {
return findingIds;
}

public void setFindingIds(List<String> findingIds) {
this.findingIds = findingIds;
public String getMonitorId() {
return monitorId;
}

public String getMonitorName() {
return monitorName;
}
}
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.securityanalytics.threatIntel.action.monitor.response.GetThreatIntelAlertsResponse;
import org.opensearch.securityanalytics.threatIntel.sacommons.monitor.ThreatIntelMonitorActions;

public class GetThreatIntelAlertsAction extends ActionType<GetThreatIntelAlertsResponse> {

public static final GetThreatIntelAlertsAction INSTANCE = new GetThreatIntelAlertsAction();
public static final String NAME = ThreatIntelMonitorActions.GET_THREAT_INTEL_ALERTS_ACTION_NAME;

public GetThreatIntelAlertsAction() {
super(NAME, GetThreatIntelAlertsResponse::new);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package org.opensearch.securityanalytics.threatIntel.action.monitor.request;

import org.opensearch.action.ActionRequest;
import org.opensearch.action.ActionRequestValidationException;
import org.opensearch.commons.alerting.model.Table;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.io.stream.StreamOutput;

import java.io.IOException;
import java.time.Instant;

public class GetThreatIntelAlertsRequest extends ActionRequest {

private final String monitorId;
private final Table table;
private final String severityLevel;
private final String alertState;
private final Instant startTime;
private final Instant endTime;

public GetThreatIntelAlertsRequest(
String monitorId,
Table table,
String severityLevel,
String alertState,
Instant startTime,
Instant endTime
) {
super();
this.monitorId = monitorId;
this.table = table;
this.severityLevel = severityLevel;
this.alertState = alertState;
this.startTime = startTime;
this.endTime = endTime;
}

public GetThreatIntelAlertsRequest(
Table table,
String severityLevel,
String alertState,
Instant startTime,
Instant endTime
) {
super();
this.monitorId = null;
this.table = table;
this.severityLevel = severityLevel;
this.alertState = alertState;
this.startTime = startTime;
this.endTime = endTime;
}

public GetThreatIntelAlertsRequest(StreamInput sin) throws IOException {
this(
sin.readOptionalString(),
Table.readFrom(sin),
sin.readString(),
sin.readString(),
sin.readOptionalInstant(),
sin.readOptionalInstant()
);
}

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

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeOptionalString(monitorId);
table.writeTo(out);
out.writeString(severityLevel);
out.writeString(alertState);
out.writeOptionalInstant(startTime);
out.writeOptionalInstant(endTime);
}

public String getmonitorId() {
return monitorId;
}

public Table getTable() {
return table;
}

public String getSeverityLevel() {
return severityLevel;
}

public String getAlertState() {
return alertState;
}

public Instant getStartTime() {
return startTime;
}

public Instant getEndTime() {
return endTime;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.opensearch.securityanalytics.threatIntel.action.monitor.response;

import org.opensearch.core.action.ActionResponse;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.io.stream.StreamOutput;
import org.opensearch.core.xcontent.ToXContentObject;
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.securityanalytics.threatIntel.sacommons.monitor.ThreatIntelAlertDto;

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

public class GetThreatIntelAlertsResponse extends ActionResponse implements ToXContentObject {

private static final String ALERTS_FIELD = "alerts";
private static final String TOTAL_ALERTS_FIELD = "total_alerts";

private List<ThreatIntelAlertDto> alerts;
private Integer totalAlerts;

public GetThreatIntelAlertsResponse(List<ThreatIntelAlertDto> alerts, Integer totalAlerts) {
super();
this.alerts = alerts;
this.totalAlerts = totalAlerts;
}

public GetThreatIntelAlertsResponse(StreamInput sin) throws IOException {
this(
Collections.unmodifiableList(sin.readList(ThreatIntelAlertDto::new)),
sin.readInt()
);
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeCollection(this.alerts);
out.writeInt(this.totalAlerts);
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject()
.field(ALERTS_FIELD, alerts)
.field(TOTAL_ALERTS_FIELD, totalAlerts);
return builder.endObject();
}

public List<ThreatIntelAlertDto> getAlerts() {
return this.alerts;
}

public Integer getTotalAlerts() {
return this.totalAlerts;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public void bulkIndexEntities(List<Entity> newEntityList, List<Entity> updatedEn
IndexRequest indexRequest = new IndexRequest(getEntityAliasName())
.id(entity.getId())
.source(entity.toXContent(XContentFactory.jsonBuilder(), ToXContent.EMPTY_PARAMS))
.opType(DocWriteRequest.OpType.UPDATE);
.opType(DocWriteRequest.OpType.INDEX);
bulkRequest.add(indexRequest);
if (
bulkRequest.requests().size() == batchSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public void searchShard(
ActionListener<SearchHits> listener) {

if (prevSeqNo != null && prevSeqNo.equals(maxSeqNo) && maxSeqNo != 0L) {
log.debug("Seqquence number unchanged.");
log.debug("Sequence number unchanged.");
listener.onResponse(SearchHits.empty());
}

Expand Down
Loading