Skip to content
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 @@ -9,8 +9,10 @@
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.*;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.time.Instant;

Expand Down Expand Up @@ -38,6 +40,9 @@ public class UtmAlertResponseRule implements Serializable {
private String agentPlatform;
@Column(name = "excluded_agents")
private String excludedAgents;
@Size(max = 500)
@Column(name = "default_agent" , length = 500)
private String defaultAgent;
@CreatedBy
@Column(name = "created_by", nullable = false, length = 50, updatable = false)
private String createdBy;
Expand All @@ -62,6 +67,7 @@ public UtmAlertResponseRule(UtmAlertResponseRuleDTO dto) {
this.ruleCmd = dto.getCommand();
this.ruleActive = dto.getActive();
this.agentPlatform = dto.getAgentPlatform();
this.defaultAgent = dto.getDefaultAgent();
if (!CollectionUtils.isEmpty(dto.getExcludedAgents()))
this.excludedAgents = String.join(",", dto.getExcludedAgents());
else
Expand Down Expand Up @@ -132,6 +138,14 @@ public void setExcludedAgents(String excludedAgents) {
this.excludedAgents = excludedAgents;
}

public String getDefaultAgent() {
return defaultAgent;
}

public void setDefaultAgent(String defaultAgent) {
this.defaultAgent = defaultAgent;
}

public String getCreatedBy() {
return createdBy;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,48 +129,85 @@ public void evaluateRules(List<AlertType> alerts) {
return;

List<UtmAlertResponseRule> rules = alertResponseRuleRepository.findAllByRuleActiveIsTrue();
if (CollectionUtils.isEmpty(rules))
return;

// Excluding alerts tagged as false positive
alerts = alerts.stream().filter(a -> (CollectionUtils.isEmpty(a.getTags()) || !a.getTags().contains("False positive")))
.collect(Collectors.toList());

// Do nothing if there is no valid alerts to check
if (CollectionUtils.isEmpty(alerts))
return;

String alertJsonArray = new Gson().toJson(alerts);
for (UtmAlertResponseRule rule : rules) {
List<FilterType> conditions = new ArrayList<>();
List<String> agentNames = networkScanRepository.findAgentNamesByPlatform(rule.getAgentPlatform());
if (!CollectionUtils.isEmpty(agentNames))
conditions.add(new FilterType(Constants.alertDataSourceKeyword, OperatorType.IS_ONE_OF, agentNames));

if (StringUtils.hasText(rule.getRuleConditions()))
conditions.addAll(new Gson().fromJson(rule.getRuleConditions(), TypeToken.getParameterized(List.class, FilterType.class).getType()));
if (CollectionUtils.isEmpty(agentNames))
continue;

// Matching agents (these are the alerts made from logs coming from an agent)
//------------------------------------------------------------------------------------------
createResponseRuleExecution(rule,alertJsonArray,agentNames,true);

// Then the alerts that match the filters but aren't from an agent, gets executed using the default agent if there is one
//-----------------------------------------------------------------------------------------------------------------------
if (StringUtils.hasText(rule.getDefaultAgent())) {
createResponseRuleExecution(rule,alertJsonArray,agentNames,false);
}
}
} catch (Exception e) {
String msg = ctx + ": " + e.getLocalizedMessage();
log.error(msg);
eventService.createEvent(msg, ApplicationEventType.ERROR);
}
}

private void createResponseRuleExecution (UtmAlertResponseRule rule, String alertJsonArray, List<String> agentNames, boolean isAgent) throws Exception {
final String ctx = CLASSNAME + ".createResponseRuleExecution";
List<FilterType> conditions = new ArrayList<>();
try {
// Common conditions
if (StringUtils.hasText(rule.getRuleConditions()))
conditions.addAll(new Gson().fromJson(rule.getRuleConditions(), TypeToken.getParameterized(List.class, FilterType.class).getType()));

if (StringUtils.hasText(rule.getExcludedAgents()))
conditions.add(new FilterType(Constants.alertDataSourceKeyword, OperatorType.IS_NOT_ONE_OF, List.of(rule.getExcludedAgents().split(","))));
if (StringUtils.hasText(rule.getExcludedAgents()))
conditions.add(new FilterType(Constants.alertDataSourceKeyword, OperatorType.IS_NOT_ONE_OF, List.of(rule.getExcludedAgents().split(","))));

Filter filter = buildFilters(conditions);
List<?> matches = UtilJson.read("$[?]", alertJsonArray, filter);
// Specific condition for agent and non agents
if (isAgent) {
conditions.add(new FilterType(Constants.alertDataSourceKeyword, OperatorType.IS_ONE_OF, agentNames));
} else {
conditions.add(new FilterType(Constants.alertDataSourceKeyword, OperatorType.IS_NOT_ONE_OF, agentNames));
}

if (CollectionUtils.isEmpty(matches))
continue;
// Processing the alerts and generating the rule executions
Filter filter = buildFilters(conditions);
List<?> matches = UtilJson.read("$[?]", alertJsonArray, filter);

if (!CollectionUtils.isEmpty(matches)) {

for (Object match : matches) {
String matchAsJson = new Gson().toJson(match);

UtmAlertResponseRuleExecution exe = new UtmAlertResponseRuleExecution();
exe.setAgent(UtilJson.read("$.dataSource", matchAsJson));
// Execution agent takes the rule's default agent if the alert was generated by logs from non agent datasource
if (isAgent) {
exe.setAgent(UtilJson.read("$.dataSource", matchAsJson));
} else {
exe.setAgent(rule.getDefaultAgent());
}

exe.setAlertId(UtilJson.read("$.id", matchAsJson));
exe.setRuleId(rule.getId());
exe.setCommand(buildCommand(rule.getRuleCmd(), matchAsJson));
exe.setExecutionStatus(RuleExecutionStatus.PENDING);
alertResponseRuleExecutionRepository.save(exe);
}
}

} catch (Exception e) {
String msg = ctx + ": " + e.getLocalizedMessage();
log.error(msg);
eventService.createEvent(msg, ApplicationEventType.ERROR);
throw new Exception(msg);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class UtmAlertResponseRuleDTO {
private Boolean active;
@NotBlank
private String agentPlatform;
@Size(max = 500)
private String defaultAgent;
private List<String> excludedAgents = new ArrayList<>();
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private String createdBy;
Expand All @@ -52,6 +54,7 @@ public UtmAlertResponseRuleDTO(UtmAlertResponseRule rule) {
this.command = rule.getRuleCmd();
this.active = rule.getRuleActive();
this.agentPlatform = rule.getAgentPlatform();
this.defaultAgent = rule.getDefaultAgent();
if (StringUtils.hasText(rule.getExcludedAgents()))
this.excludedAgents.addAll(Arrays.asList(rule.getExcludedAgents().split(",")));
this.createdBy = rule.getCreatedBy();
Expand Down Expand Up @@ -112,6 +115,14 @@ public String getAgentPlatform() {
return agentPlatform;
}

public String getDefaultAgent() {
return defaultAgent;
}

public void setDefaultAgent(String defaultAgent) {
this.defaultAgent = defaultAgent;
}

public void setAgentPlatform(String agentPlatform) {
this.agentPlatform = agentPlatform;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">

<changeSet id="20240131001" author="Freddy">
<addColumn tableName="utm_alert_response_rule">
<column name="default_agent" type="varchar(500)">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>
2 changes: 2 additions & 0 deletions backend/src/main/resources/config/liquibase/master.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@

<include file="config/liquibase/changelog/20240109001_modifying_requirement_for_configuration_parameters.xml" relativeToChangelogFile="false"/>

<include file="config/liquibase/changelog/20240131001_add_default_agent_utm_alert_response_rule.xml" relativeToChangelogFile="false"/>

</databaseChangeLog>