diff --git a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDao.java b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDao.java index 2fb9686687..a64f5ad5b6 100644 --- a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDao.java +++ b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDao.java @@ -294,11 +294,14 @@ protected Document buildCreateDocument(MultiGetResponse multiGetResponse, List index) throws IOException { - // We have an update to a meta alert itself (e.g. adding a document, etc.) Calculate scores - // and defer the final result to the Elasticsearch DAO. - MetaScores metaScores = calculateMetaScores(update); - update.getDocument().putAll(metaScores.getMetaScores()); - update.getDocument().put(threatTriageField, metaScores.getMetaScores().get(threatSort)); + // We have an update to a meta alert itself + // If we've updated the alerts field (i.e add/remove), recalculate meta alert scores. + if (update.getDocument().containsKey(MetaAlertDao.ALERT_FIELD)) { + MetaScores metaScores = calculateMetaScores(update); + update.getDocument().putAll(metaScores.getMetaScores()); + update.getDocument().put(threatTriageField, metaScores.getMetaScores().get(threatSort)); + } + indexDao.update(update, index); } diff --git a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDaoTest.java b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDaoTest.java index 74e1275a11..ad2e7f3c8b 100644 --- a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDaoTest.java +++ b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDaoTest.java @@ -21,6 +21,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.IOException; @@ -59,6 +61,7 @@ import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.junit.Test; +import org.mockito.Mock; public class ElasticsearchMetaAlertDaoTest { @@ -423,4 +426,49 @@ public void testCalculateMetaScoresList() { MetaScores actual = metaAlertDao.calculateMetaScores(doc); assertEquals(expected.getMetaScores(), actual.getMetaScores()); } + + @Test + public void testHandleMetaUpdateNonAlert() throws IOException { + ElasticsearchDao mockEsDao= mock(ElasticsearchDao.class); + + Map docMap = new HashMap<>(); + docMap.put(MetaAlertDao.STATUS_FIELD, MetaAlertStatus.ACTIVE.getStatusString()); + Document update = new Document(docMap, "guid", MetaAlertDao.METAALERT_TYPE, 0L); + + ElasticsearchMetaAlertDao metaAlertDao = new ElasticsearchMetaAlertDao(mockEsDao); + metaAlertDao.handleMetaUpdate(update, Optional.of(MetaAlertDao.METAALERTS_INDEX)); + verify(mockEsDao, times(1)) + .update(update, Optional.of(MetaAlertDao.METAALERTS_INDEX)); + } + + @Test + public void testHandleMetaUpdateAlert() throws IOException { + ElasticsearchDao mockEsDao= mock(ElasticsearchDao.class); + + Map alertMap = new HashMap<>(); + alertMap.put(MetaAlertDao.THREAT_FIELD_DEFAULT, 10.0d); + List> alertList = new ArrayList<>(); + alertList.add(alertMap); + + Map docMapBefore = new HashMap<>(); + docMapBefore.put(MetaAlertDao.ALERT_FIELD, alertList); + Document before = new Document(docMapBefore, "guid", MetaAlertDao.METAALERT_TYPE, 0L); + + Map docMapAfter = new HashMap<>(); + docMapAfter.putAll(docMapBefore); + docMapAfter.put("average", 10.0d); + docMapAfter.put("min", 10.0d); + docMapAfter.put("median", 10.0d); + docMapAfter.put("max", 10.0d); + docMapAfter.put("count", 1L); + docMapAfter.put("sum", 10.0d); + docMapAfter.put(MetaAlertDao.THREAT_FIELD_DEFAULT, 10.0d); + Document after = new Document(docMapAfter, "guid", MetaAlertDao.METAALERT_TYPE, 0L); + + ElasticsearchMetaAlertDao metaAlertDao = new ElasticsearchMetaAlertDao(mockEsDao); + metaAlertDao.handleMetaUpdate(before, Optional.of(MetaAlertDao.METAALERTS_INDEX)); + + verify(mockEsDao, times(1)) + .update(after, Optional.of(MetaAlertDao.METAALERTS_INDEX)); + } } diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/Document.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/Document.java index 461ce3e108..b5fcb025f7 100644 --- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/Document.java +++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/Document.java @@ -92,4 +92,37 @@ public String toString() { ", sensorType='" + sensorType + '\'' + '}'; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Document document1 = (Document) o; + + if (timestamp != null ? !timestamp.equals(document1.timestamp) : document1.timestamp != null) { + return false; + } + if (document != null ? !document.equals(document1.document) : document1.document != null) { + return false; + } + if (guid != null ? !guid.equals(document1.guid) : document1.guid != null) { + return false; + } + return sensorType != null ? sensorType.equals(document1.sensorType) + : document1.sensorType == null; + } + + @Override + public int hashCode() { + int result = timestamp != null ? timestamp.hashCode() : 0; + result = 31 * result + (document != null ? document.hashCode() : 0); + result = 31 * result + (guid != null ? guid.hashCode() : 0); + result = 31 * result + (sensorType != null ? sensorType.hashCode() : 0); + return result; + } }