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

adds threat intel alert status update API #1104

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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 @@ -135,6 +135,7 @@
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.action.monitor.UpdateThreatIntelAlertStatusAction;
import org.opensearch.securityanalytics.threatIntel.common.TIFLockService;
import org.opensearch.securityanalytics.threatIntel.feedMetadata.BuiltInTIFMetadataLoader;
import org.opensearch.securityanalytics.threatIntel.iocscan.dao.IocFindingService;
Expand All @@ -155,6 +156,7 @@
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.resthandler.monitor.RestUpdateThreatIntelAlertsStatusAction;
import org.opensearch.securityanalytics.threatIntel.service.DetectorThreatIntelService;
import org.opensearch.securityanalytics.threatIntel.service.SATIFSourceConfigManagementService;
import org.opensearch.securityanalytics.threatIntel.service.SATIFSourceConfigService;
Expand All @@ -172,6 +174,7 @@
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.threatIntel.transport.monitor.TransportUpdateThreatIntelAlertStatusAction;
import org.opensearch.securityanalytics.transport.TransportAckCorrelationAlertsAction;
import org.opensearch.securityanalytics.transport.TransportAcknowledgeAlertsAction;
import org.opensearch.securityanalytics.transport.TransportCorrelateFindingAction;
Expand Down Expand Up @@ -241,6 +244,7 @@ public class SecurityAnalyticsPlugin extends Plugin implements ActionPlugin, Map
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 THREAT_INTEL_ALERTS_STATUS_URI = PLUGINS_BASE_URI + "/threat_intel/alerts/status";
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 @@ -323,7 +327,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,threatIntelAlertService,
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 @@ -356,6 +360,7 @@ public List<RestHandler> getRestHandlers(Settings settings,
new RestGetMappingsViewAction(),
new RestGetAlertsAction(),
new RestGetThreatIntelAlertsAction(),
new RestUpdateThreatIntelAlertsStatusAction(),
new RestIndexRuleAction(),
new RestSearchRuleAction(),
new RestDeleteRuleAction(),
Expand Down Expand Up @@ -522,6 +527,7 @@ public List<Setting<?>> getSettings() {
new ActionPlugin.ActionHandler<>(ListCorrelationsAction.INSTANCE, TransportListCorrelationAction.class),
new ActionPlugin.ActionHandler<>(SearchCorrelationRuleAction.INSTANCE, TransportSearchCorrelationRuleAction.class),
new ActionPlugin.ActionHandler<>(GetThreatIntelAlertsAction.INSTANCE, TransportGetThreatIntelAlertsAction.class),
new ActionPlugin.ActionHandler<>(UpdateThreatIntelAlertStatusAction.INSTANCE, TransportUpdateThreatIntelAlertStatusAction.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 @@ -7,6 +7,8 @@
import org.opensearch.core.common.io.stream.StreamOutput;
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.core.xcontent.XContentParser;
import org.opensearch.index.seqno.SequenceNumbers;
import org.opensearch.securityanalytics.threatIntel.sacommons.monitor.ThreatIntelAlertDto;
import org.opensearch.securityanalytics.util.XContentUtils;

import java.io.IOException;
Expand Down Expand Up @@ -40,13 +42,17 @@ public class ThreatIntelAlert extends BaseEntity {
public static final String IOC_VALUE_FIELD = "ioc_value";
public static final String IOC_TYPE_FIELD = "ioc_type";
public static final String FINDING_IDS_FIELD = "finding_ids";
public static final String SEQ_NO_FIELD = "seq_no";
public static final String PRIMARY_TERM_FIELD = "primary_term";
public static final String NO_ID = "";
public static final long NO_VERSION = 1L;
public static final long NO_SCHEMA_VERSION = 0;

private final String id;
private final long version;
private final long schemaVersion;
private final long seqNo;
private final long primaryTerm;
private final User user;
private final String triggerName;
private final String triggerId;
Expand Down Expand Up @@ -89,6 +95,55 @@ public ThreatIntelAlert(
this.id = id != null ? id : NO_ID;
this.version = version != 0 ? version : NO_VERSION;
this.schemaVersion = schemaVersion;
this.seqNo = SequenceNumbers.UNASSIGNED_SEQ_NO;
this.primaryTerm = SequenceNumbers.UNASSIGNED_PRIMARY_TERM;
this.user = user;
this.triggerId = triggerId;
this.triggerName = triggerName;
this.monitorId = monitorId;
this.monitorName = monitorName;
this.state = state;
this.startTime = startTime;
this.endTime = endTime;
this.acknowledgedTime = acknowledgedTime;
this.errorMessage = errorMessage;
this.severity = severity;
this.iocValue = iocValue;
this.iocType = iocType;
this.actionExecutionResults = actionExecutionResults;
this.lastUpdatedTime = lastUpdatedTime;
this.findingIds = findingIds;
}

public ThreatIntelAlert(
String id,
long version,
long schemaVersion,
long seqNo,
long primaryTerm,
User user,
String triggerId,
String triggerName,
String monitorId,
String monitorName,
Alert.State state,
Instant startTime,
Instant endTime,
Instant lastUpdatedTime,
Instant acknowledgedTime,
String errorMessage,
String severity,
String iocValue,
String iocType,
List<ActionExecutionResult> actionExecutionResults,
List<String> findingIds
) {

this.id = id != null ? id : NO_ID;
this.version = version != 0 ? version : NO_VERSION;
this.schemaVersion = schemaVersion;
this.seqNo = seqNo;
this.primaryTerm = primaryTerm;
this.user = user;
this.triggerId = triggerId;
this.triggerName = triggerName;
Expand All @@ -111,6 +166,8 @@ public ThreatIntelAlert(StreamInput sin) throws IOException {
this.id = sin.readString();
this.version = sin.readLong();
this.schemaVersion = sin.readLong();
this.seqNo = sin.readLong();
this.primaryTerm = sin.readLong();
this.user = sin.readBoolean() ? new User(sin) : null;
this.triggerId = sin.readString();
this.triggerName = sin.readString();
Expand All @@ -134,6 +191,8 @@ public ThreatIntelAlert(ThreatIntelAlert currentAlert, List<String> findingIds)
this.id = currentAlert.id;
this.version = currentAlert.version;
this.schemaVersion = currentAlert.schemaVersion;
this.seqNo =currentAlert.seqNo;
this.primaryTerm =currentAlert.primaryTerm;
this.user = currentAlert.user;
this.triggerId = currentAlert.triggerId;
this.triggerName = currentAlert.triggerName;
Expand All @@ -151,6 +210,32 @@ public ThreatIntelAlert(ThreatIntelAlert currentAlert, List<String> findingIds)
this.lastUpdatedTime = Instant.now();
}

public static ThreatIntelAlert updateStatus(ThreatIntelAlert currentAlert, Alert.State newState) {
return new ThreatIntelAlert(
currentAlert.id,
currentAlert.version,
currentAlert.schemaVersion,
currentAlert.seqNo,
currentAlert.primaryTerm,
currentAlert.user,
currentAlert.triggerId,
currentAlert.triggerName,
currentAlert.monitorId,
currentAlert.monitorName,
newState,
currentAlert.startTime,
newState.equals(Alert.State.COMPLETED) ? Instant.now() : currentAlert.endTime,
Instant.now(),
newState.equals(Alert.State.ACKNOWLEDGED) ? Instant.now() : currentAlert.endTime,
currentAlert.errorMessage,
currentAlert.severity,
currentAlert.iocValue,
currentAlert.iocType,
currentAlert.actionExecutionResults,
currentAlert.getFindingIds()
);
}

public boolean isAcknowledged() {
return state == Alert.State.ACKNOWLEDGED;
}
Expand All @@ -160,6 +245,8 @@ public void writeTo(StreamOutput out) throws IOException {
out.writeString(id);
out.writeLong(version);
out.writeLong(schemaVersion);
out.writeLong(seqNo);
out.writeLong(primaryTerm);
out.writeBoolean(user != null);
if (user != null) {
user.writeTo(out);
Expand All @@ -181,9 +268,128 @@ public void writeTo(StreamOutput out) throws IOException {
out.writeStringCollection(findingIds);
}

public static ThreatIntelAlert parse(XContentParser xcp, long version, long seqNo, long primaryTerm) throws IOException {
String id = NO_ID;
long schemaVersion = NO_SCHEMA_VERSION;
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;
Instant endTime = null;
Instant acknowledgedTime = null;
Instant lastUpdatedTime = null;
String errorMessage = null;
List<ActionExecutionResult> actionExecutionResults = new ArrayList<>();
String iocValue = null;
String iocType = null;
List<String> findingIds = new ArrayList<>();

while (xcp.nextToken() != XContentParser.Token.END_OBJECT) {
String fieldName = xcp.currentName();
xcp.nextToken();
switch (fieldName) {
case USER_FIELD:
user = xcp.currentToken() == XContentParser.Token.VALUE_NULL ? null : User.parse(xcp);
break;
case ALERT_ID_FIELD:
id = xcp.text();
break;
case IOC_VALUE_FIELD:
iocValue = xcp.textOrNull();
break;
case IOC_TYPE_FIELD:
iocType = xcp.textOrNull();
break;
case ALERT_VERSION_FIELD:
version = xcp.longValue();
break;
case SCHEMA_VERSION_FIELD:
schemaVersion = xcp.intValue();
break;
case SEQ_NO_FIELD:
seqNo = xcp.longValue();
break;
case PRIMARY_TERM_FIELD:
primaryTerm = xcp.longValue();
break;
case TRIGGER_ID_FIELD:
triggerId = xcp.text();
break;
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;
case ERROR_MESSAGE_FIELD:
errorMessage = xcp.textOrNull();
break;
case SEVERITY_FIELD:
severity = xcp.text();
break;
case ACTION_EXECUTION_RESULTS_FIELD:
ensureExpectedToken(XContentParser.Token.START_ARRAY, xcp.currentToken(), xcp);
while (xcp.nextToken() != XContentParser.Token.END_ARRAY) {
actionExecutionResults.add(ActionExecutionResult.parse(xcp));
}
break;
case START_TIME_FIELD:
startTime = getInstant(xcp);
break;
case END_TIME_FIELD:
endTime = getInstant(xcp);
break;
case ACKNOWLEDGED_TIME_FIELD:
acknowledgedTime = getInstant(xcp);
break;
case LAST_UPDATED_TIME_FIELD:
lastUpdatedTime = getInstant(xcp);
break;
case FINDING_IDS_FIELD:
ensureExpectedToken(XContentParser.Token.START_ARRAY, xcp.currentToken(), xcp);
while (xcp.nextToken() != XContentParser.Token.END_ARRAY) {
findingIds.add(xcp.text());
}
default:
xcp.skipChildren();
}
}

return new ThreatIntelAlert(id,
version,
schemaVersion,
seqNo,
primaryTerm,
user,
triggerId,
triggerName,
monitorId,
monitorName,
state,
startTime,
endTime,
acknowledgedTime,
lastUpdatedTime,
errorMessage,
severity,
iocValue, iocType, actionExecutionResults, findingIds);
}

public static ThreatIntelAlert parse(XContentParser xcp, long version) throws IOException {
String id = NO_ID;
long schemaVersion = NO_SCHEMA_VERSION;
long seqNo = SequenceNumbers.UNASSIGNED_SEQ_NO;
long primaryTerm = SequenceNumbers.UNASSIGNED_PRIMARY_TERM;
User user = null;
String triggerId = null;
String triggerName = null;
Expand Down Expand Up @@ -223,6 +429,12 @@ public static ThreatIntelAlert parse(XContentParser xcp, long version) throws IO
case SCHEMA_VERSION_FIELD:
schemaVersion = xcp.intValue();
break;
case SEQ_NO_FIELD:
seqNo = xcp.longValue();
break;
case PRIMARY_TERM_FIELD:
primaryTerm = xcp.longValue();
break;
case TRIGGER_ID_FIELD:
triggerId = xcp.text();
break;
Expand Down Expand Up @@ -275,6 +487,8 @@ public static ThreatIntelAlert parse(XContentParser xcp, long version) throws IO
return new ThreatIntelAlert(id,
version,
schemaVersion,
seqNo,
primaryTerm,
user,
triggerId,
triggerName,
Expand Down Expand Up @@ -313,6 +527,8 @@ private XContentBuilder createXContentBuilder(XContentBuilder builder, boolean s
.field(ALERT_ID_FIELD, id)
.field(ALERT_VERSION_FIELD, version)
.field(SCHEMA_VERSION_FIELD, schemaVersion)
.field(SEQ_NO_FIELD, seqNo)
.field(PRIMARY_TERM_FIELD, primaryTerm)
.field(TRIGGER_NAME_FIELD, triggerName)
.field(TRIGGER_ID_FIELD, triggerId)
.field(MONITOR_ID_FIELD, monitorId)
Expand Down Expand Up @@ -428,4 +644,12 @@ public String getMonitorId() {
public String getMonitorName() {
return monitorName;
}

public long getSeqNo() {
return seqNo;
}

public long getPrimaryTerm() {
return primaryTerm;
}
}
Loading
Loading