You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by le...@apache.org on 2018/05/23 14:34:32 UTC
[5/7] metron git commit: METRON-1421 Create a SolrMetaAlertDao
(justinleet) closes apache/metron#970
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/IndexDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/IndexDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/IndexDao.java
index fe546bd..4187428 100644
--- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/IndexDao.java
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/IndexDao.java
@@ -17,151 +17,18 @@
*/
package org.apache.metron.indexing.dao;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import org.apache.metron.common.utils.JSONUtils;
-import org.apache.metron.indexing.dao.search.FieldType;
-import org.apache.metron.indexing.dao.search.GetRequest;
-import org.apache.metron.indexing.dao.search.GroupRequest;
-import org.apache.metron.indexing.dao.search.GroupResponse;
-import org.apache.metron.indexing.dao.search.InvalidSearchException;
-import org.apache.metron.indexing.dao.search.SearchRequest;
-import org.apache.metron.indexing.dao.search.SearchResponse;
-import org.apache.metron.indexing.dao.update.Document;
-import org.apache.metron.indexing.dao.update.OriginalNotFoundException;
-import org.apache.metron.indexing.dao.update.PatchRequest;
-import org.apache.metron.indexing.dao.update.ReplaceRequest;
+import org.apache.metron.indexing.dao.search.SearchDao;
+import org.apache.metron.indexing.dao.update.UpdateDao;
/**
* The IndexDao provides a common interface for retrieving and storing data in a variety of persistent stores.
* Document reads and writes require a GUID and sensor type with an index being optional.
*/
-public interface IndexDao {
-
- /**
- * Return search response based on the search request
- *
- * @param searchRequest
- * @return
- * @throws InvalidSearchException
- */
- SearchResponse search(SearchRequest searchRequest) throws InvalidSearchException;
-
- GroupResponse group(GroupRequest groupRequest) throws InvalidSearchException;
+public interface IndexDao extends UpdateDao, SearchDao, RetrieveLatestDao, ColumnMetadataDao {
/**
* Initialize the DAO with the AccessConfig object.
- * @param config
+ * @param config The config to use for initialization
*/
void init(AccessConfig config);
-
- /**
- * Return the latest version of a document given the GUID and the sensor type.
- *
- * @param guid The GUID for the document
- * @param sensorType The sensor type of the document
- * @return The Document matching or null if not available.
- * @throws IOException
- */
- Document getLatest(String guid, String sensorType) throws IOException;
-
- /**
- * Return a list of the latest versions of documents given a list of GUIDs and sensor types.
- *
- * @param getRequests A list of get requests for documents
- * @return A list of documents matching or an empty list in not available.
- * @throws IOException
- */
- Iterable<Document> getAllLatest(List<GetRequest> getRequests) throws IOException;
-
- /**
- * Return the latest version of a document given a GetRequest.
- * @param request The GetRequest which indicates the GUID and sensor type.
- * @return Optionally the document (dependent upon existence in the index).
- * @throws IOException
- */
- default Optional<Map<String, Object>> getLatestResult(GetRequest request) throws IOException {
- Document ret = getLatest(request.getGuid(), request.getSensorType());
- if(ret == null) {
- return Optional.empty();
- }
- else {
- return Optional.ofNullable(ret.getDocument());
- }
- }
-
- /**
- * Update a given Document and optionally the index where the document exists. This is a full update,
- * meaning the current document will be replaced if it exists or a new document will be created if it does
- * not exist. Partial updates are not supported in this method.
- *
- * @param update The document to replace from the index.
- * @param index The index where the document lives.
- * @throws IOException
- */
- void update(Document update, Optional<String> index) throws IOException;
-
- /**
- * Similar to the update method but accepts multiple documents and performs updates in batch.
- *
- * @param updates A map of the documents to update to the index where they live.
- * @throws IOException
- */
- void batchUpdate(Map<Document, Optional<String>> updates) throws IOException;
-
- /**
- * Update a document in an index given a JSON Patch (see RFC 6902 at https://tools.ietf.org/html/rfc6902)
- * @param request The patch request
- * @param timestamp Optionally a timestamp to set. If not specified then current time is used.
- * @throws OriginalNotFoundException If the original is not found, then it cannot be patched.
- * @throws IOException
- */
- default void patch( PatchRequest request
- , Optional<Long> timestamp
- ) throws OriginalNotFoundException, IOException {
- Document d = getPatchedDocument(request, timestamp);
- update(d, Optional.ofNullable(request.getIndex()));
- }
-
- default Document getPatchedDocument(PatchRequest request
- , Optional<Long> timestamp
- ) throws OriginalNotFoundException, IOException {
- Map<String, Object> latest = request.getSource();
- if(latest == null) {
- Document latestDoc = getLatest(request.getGuid(), request.getSensorType());
- if(latestDoc != null && latestDoc.getDocument() != null) {
- latest = latestDoc.getDocument();
- }
- else {
- throw new OriginalNotFoundException("Unable to patch an document that doesn't exist and isn't specified.");
- }
- }
- Map<String, Object> updated = JSONUtils.INSTANCE.applyPatch(request.getPatch(), latest);
- return new Document(updated
- , request.getGuid()
- , request.getSensorType()
- , timestamp.orElse(System.currentTimeMillis()));
- }
-
- /**
- * Replace a document in an index.
- * @param request The replacement request.
- * @param timestamp The timestamp (optional) of the update. If not specified, then current time will be used.
- * @throws IOException
- */
- default void replace( ReplaceRequest request
- , Optional<Long> timestamp
- ) throws IOException {
- Document d = new Document(request.getReplacement()
- , request.getGuid()
- , request.getSensorType()
- , timestamp.orElse(System.currentTimeMillis())
- );
- update(d, Optional.ofNullable(request.getIndex()));
- }
-
- Map<String, FieldType> getColumnMetadata(List<String> indices) throws IOException;
}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/MetaAlertDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/MetaAlertDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/MetaAlertDao.java
deleted file mode 100644
index 4530d2a..0000000
--- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/MetaAlertDao.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.metron.indexing.dao;
-
-import java.util.List;
-import java.util.Optional;
-import java.io.IOException;
-import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateRequest;
-import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateResponse;
-import org.apache.metron.indexing.dao.metaalert.MetaAlertStatus;
-import org.apache.metron.indexing.dao.search.GetRequest;
-import org.apache.metron.indexing.dao.search.InvalidCreateException;
-import org.apache.metron.indexing.dao.search.InvalidSearchException;
-import org.apache.metron.indexing.dao.search.SearchResponse;
-
-/**
- * The MetaAlertDao exposes methods for interacting with meta alerts. Meta alerts are objects that contain
- * alerts and summary statistics based on the scores of these alerts. Meta alerts are returned in searches
- * just as alerts are and match based on the field values of child alerts. If a child alert matches a search
- * the meta alert will be returned while the original child alert will not. A meta alert also contains a
- * status field that controls it's inclusion in search results and a groups field that can be used to track
- * the groups a meta alert was created from.
- *
- * The structure of a meta alert is as follows:
- * {
- * "guid": "meta alert guid",
- * "timestamp": timestamp,
- * "source:type": "metaalert",
- * "alerts": [ array of child alerts ],
- * "status": "active or inactive",
- * "groups": [ array of group names ],
- * "average": 10,
- * "max": 10,
- * "threat:triage:score": 30,
- * "count": 3,
- * "sum": 30,
- * "min": 10,
- * "median": 10
- * }
- *
- * A child alert that has been added to a meta alert will store the meta alert GUID in a "metaalerts" field.
- * This field is an array of meta alert GUIDs, meaning a child alert can be contained in multiple meta alerts.
- * Any update to a child alert will trigger an update to the meta alert so that the alert inside a meta alert
- * and the original alert will be kept in sync.
- *
- * Other fields can be added to a meta alert through the patch method on the IndexDao interface. However, attempts
- * to directly change the "alerts" or "status" field will result in an exception.
- */
-public interface MetaAlertDao extends IndexDao {
-
- String METAALERTS_INDEX = "metaalert_index";
- String METAALERT_TYPE = "metaalert";
- String METAALERT_FIELD = "metaalerts";
- String METAALERT_DOC = METAALERT_TYPE + "_doc";
- String THREAT_FIELD_DEFAULT = "threat:triage:score";
- String THREAT_SORT_DEFAULT = "sum";
- String ALERT_FIELD = "alert";
- String STATUS_FIELD = "status";
- String GROUPS_FIELD = "groups";
-
- /**
- * Given an alert GUID, retrieve all associated meta alerts.
- * @param guid The alert GUID to be searched for
- * @return All meta alerts with a child alert having the GUID
- * @throws InvalidSearchException If a problem occurs with the search
- */
- SearchResponse getAllMetaAlertsForAlert(String guid) throws InvalidSearchException;
-
- /**
- * Creates a meta alert from a list of child alerts. The most recent version of each child alert is
- * retrieved using the DAO abstractions.
- *
- * @param request A request object containing get requests for alerts to be added and a list of groups
- * @return A response indicating success or failure along with the GUID of the new meta alert
- * @throws InvalidCreateException If a malformed create request is provided
- * @throws IOException If a problem occurs during communication
- */
- MetaAlertCreateResponse createMetaAlert(MetaAlertCreateRequest request)
- throws InvalidCreateException, IOException;
-
-
- /**
- * Adds a list of alerts to an existing meta alert. This will add each alert object to the "alerts" array in the meta alert
- * and also add the meta alert GUID to each child alert's "metaalerts" array. After alerts have been added the
- * meta alert scores are recalculated. Any alerts already in the meta alert are skipped and no updates are
- * performed if all of the alerts are already in the meta alert. The most recent version of each child alert is
- * retrieved using the DAO abstractions. Alerts cannot be added to an 'inactive' meta alert.
- *
- * @param metaAlertGuid The meta alert GUID
- * @param getRequests Get requests for alerts to be added
- * @return True or false depending on if any alerts were added
- * @throws IOException
- */
- boolean addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> getRequests) throws IOException;
-
- /**
- * Removes a list of alerts from an existing meta alert. This will remove each alert object from the "alerts" array in the meta alert
- * and also remove the meta alert GUID from each child alert's "metaalerts" array. After alerts have been removed the
- * meta alert scores are recalculated. Any alerts not contained in the meta alert are skipped and no updates are
- * performed if no alerts can be found in the meta alert. Alerts cannot be removed from an 'inactive' meta alert.
- *
- * @param metaAlertGuid The meta alert GUID
- * @param getRequests Get requests for alerts to be removed
- * @return True or false depending on if any alerts were removed
- * @throws IOException
- */
- boolean removeAlertsFromMetaAlert(String metaAlertGuid, List<GetRequest> getRequests) throws IOException;
-
- /**
- * The meta alert status field can be set to either 'active' or 'inactive' and will control whether or not meta alerts
- * (and child alerts) appear in search results. An 'active' status will cause meta alerts to appear in search
- * results instead of it's child alerts and an 'inactive' status will suppress the meta alert from search results
- * with child alerts appearing in search results as normal. A change to 'inactive' will cause the meta alert GUID to
- * be removed from all it's child alert's "metaalerts" field. A change back to 'active' will have the opposite effect.
- *
- * @param metaAlertGuid The GUID of the meta alert
- * @param status A status value of 'active' or 'inactive'
- * @return True or false depending on if the status was changed
- * @throws IOException
- */
- boolean updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) throws IOException;
-
- /**
- * Initializes a Meta Alert DAO with default "sum" meta alert threat sorting.
- * @param indexDao The DAO to wrap for our queries.
- */
- default void init(IndexDao indexDao) {
- init(indexDao, Optional.empty());
- }
-
- /**
- * Initializes a Meta Alert DAO.
- * @param indexDao The DAO to wrap for our queries
- * @param threatSort The aggregation to use as the threat field. E.g. "sum", "median", etc.
- * null is "sum"
- */
- void init(IndexDao indexDao, Optional<String> threatSort);
-}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/RetrieveLatestDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/RetrieveLatestDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/RetrieveLatestDao.java
new file mode 100644
index 0000000..caf754c
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/RetrieveLatestDao.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.dao;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.metron.indexing.dao.search.GetRequest;
+import org.apache.metron.indexing.dao.update.Document;
+
+/**
+ * An base interface for other DAOs to extend. All DAOs are expected to be able to retrieve
+ * Documents they've stored.
+ */
+public interface RetrieveLatestDao {
+
+ /**
+ * Return the latest version of a document given the GUID and the sensor type.
+ *
+ * @param guid The GUID for the document
+ * @param sensorType The sensor type of the document
+ * @return The Document matching or null if not available.
+ * @throws IOException If an error occurs retrieving the latest document.
+ */
+ Document getLatest(String guid, String sensorType) throws IOException;
+
+ /**
+ * Return a list of the latest versions of documents given a list of GUIDs and sensor types.
+ *
+ * @param getRequests A list of get requests for documents
+ * @return A list of documents matching or an empty list in not available.
+ * @throws IOException If an error occurs retrieving the latest documents.
+ */
+ Iterable<Document> getAllLatest(List<GetRequest> getRequests) throws IOException;
+
+ /**
+ * Return the latest version of a document given a GetRequest.
+ * @param request The GetRequest which indicates the GUID and sensor type.
+ * @return Optionally the document (dependent upon existence in the index).
+ * @throws IOException If an error occurs while retrieving the document.
+ */
+ default Optional<Map<String, Object>> getLatestResult(GetRequest request) throws IOException {
+ Document ret = getLatest(request.getGuid(), request.getSensorType());
+ if (ret == null) {
+ return Optional.empty();
+ } else {
+ return Optional.ofNullable(ret.getDocument());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/DeferredMetaAlertIndexDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/DeferredMetaAlertIndexDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/DeferredMetaAlertIndexDao.java
new file mode 100644
index 0000000..1e5e723
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/DeferredMetaAlertIndexDao.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.dao.metaalert;
+
+import org.apache.metron.indexing.dao.IndexDao;
+
+/**
+ * Interface for a DAO that is allowed to defer to a child Index DAO in order to perform tasks.
+ * An example is metaalerts deferring to a base DAO.
+ */
+public interface DeferredMetaAlertIndexDao {
+
+ IndexDao getIndexDao();
+
+ String getMetAlertSensorName();
+
+ String getMetaAlertIndex();
+
+ default String getThreatTriageField() {
+ return MetaAlertConstants.THREAT_FIELD_DEFAULT;
+ }
+
+ default String getThreatSort() {
+ return MetaAlertConstants.THREAT_SORT_DEFAULT;
+ }
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertAddRemoveRequest.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertAddRemoveRequest.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertAddRemoveRequest.java
index 6183d37..a14749b 100644
--- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertAddRemoveRequest.java
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertAddRemoveRequest.java
@@ -14,7 +14,6 @@
*/
package org.apache.metron.indexing.dao.metaalert;
-import java.util.Collection;
import java.util.List;
import org.apache.metron.indexing.dao.search.GetRequest;
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertConfig.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertConfig.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertConfig.java
new file mode 100644
index 0000000..9254425
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertConfig.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.dao.metaalert;
+
+public class MetaAlertConfig {
+ private String metaAlertIndex;
+ private String threatTriageField;
+ private String threatSort;
+ private String sourceTypeField;
+
+ /**
+ * Simple object for storing and retrieving configs, primarily to make passing all the info to
+ * the sub DAOs easier.
+ * @param metaAlertIndex The metaalert index or collection we're using
+ * @param threatTriageField The threat triage field's name
+ * @param threatSort The sorting operation on the threat triage field
+ * @param sourceTypeField The source type field
+ */
+ public MetaAlertConfig(String metaAlertIndex, String threatTriageField,
+ String threatSort, String sourceTypeField) {
+ this.metaAlertIndex = metaAlertIndex;
+ this.threatTriageField = threatTriageField;
+ this.threatSort = threatSort;
+ this.sourceTypeField = sourceTypeField;
+ }
+
+ public String getMetaAlertIndex() {
+ return metaAlertIndex;
+ }
+
+ public void setMetaAlertIndex(String metaAlertIndex) {
+ this.metaAlertIndex = metaAlertIndex;
+ }
+
+ public String getThreatTriageField() {
+ return threatTriageField;
+ }
+
+ public void setThreatTriageField(String threatTriageField) {
+ this.threatTriageField = threatTriageField;
+ }
+
+ public String getThreatSort() {
+ return threatSort;
+ }
+
+ public void setThreatSort(String threatSort) {
+ this.threatSort = threatSort;
+ }
+
+ public String getSourceTypeField() {
+ return sourceTypeField;
+ }
+
+ public void setSourceTypeField(String sourceTypeField) {
+ this.sourceTypeField = sourceTypeField;
+ }
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertConstants.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertConstants.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertConstants.java
new file mode 100644
index 0000000..a055db5
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertConstants.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.dao.metaalert;
+
+public class MetaAlertConstants {
+ public static String METAALERT_TYPE = "metaalert";
+ public static String METAALERT_FIELD = "metaalerts";
+ public static String METAALERT_DOC = METAALERT_TYPE + "_doc";
+ public static String THREAT_FIELD_DEFAULT = "threat:triage:score";
+ public static String THREAT_SORT_DEFAULT = "sum";
+ public static String ALERT_FIELD = "alert";
+ public static String STATUS_FIELD = "status";
+ public static String GROUPS_FIELD = "groups";
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertDao.java
new file mode 100644
index 0000000..c9e6711
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertDao.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.dao.metaalert;
+
+import java.util.Optional;
+import org.apache.metron.indexing.dao.IndexDao;
+
+/**
+ * The MetaAlertDao exposes methods for interacting with meta alerts. Meta alerts are objects that contain
+ * alerts and summary statistics based on the scores of these alerts. Meta alerts are returned in searches
+ * just as alerts are and match based on the field values of child alerts. If a child alert matches a search
+ * the meta alert will be returned while the original child alert will not. A meta alert also contains a
+ * status field that controls it's inclusion in search results and a groups field that can be used to track
+ * the groups a meta alert was created from.
+ *
+ * </p>
+ * The structure of a meta alert is as follows:
+ * {
+ * "guid": "meta alert guid",
+ * "timestamp": timestamp,
+ * "source:type": "metaalert",
+ * "alerts": [ array of child alerts ],
+ * "status": "active or inactive",
+ * "groups": [ array of group names ],
+ * "average": 10,
+ * "max": 10,
+ * "threat:triage:score": 30,
+ * "count": 3,
+ * "sum": 30,
+ * "min": 10,
+ * "median": 10
+ * }
+ *
+ * </p>
+ * A child alert that has been added to a meta alert will store the meta alert GUID in a "metaalerts" field.
+ * This field is an array of meta alert GUIDs, meaning a child alert can be contained in multiple meta alerts.
+ * Any update to a child alert will trigger an update to the meta alert so that the alert inside a meta alert
+ * and the original alert will be kept in sync.
+ *
+ * </p>
+ * Other fields can be added to a meta alert through the patch method on the IndexDao interface. However, attempts
+ * to directly change the "alerts" or "status" field will result in an exception.
+ */
+public interface MetaAlertDao extends MetaAlertSearchDao, MetaAlertUpdateDao, IndexDao {
+
+ /**
+ * Initializes a Meta Alert DAO with default "sum" meta alert threat sorting.
+ * @param indexDao The DAO to wrap for our queries.
+ */
+ default void init(IndexDao indexDao) {
+ init(indexDao, Optional.empty());
+ }
+
+ /**
+ * Initializes a Meta Alert DAO.
+ * @param indexDao The DAO to wrap for our queries
+ * @param threatSort The aggregation to use as the threat field. E.g. "sum", "median", etc.
+ * null is "sum"
+ */
+ void init(IndexDao indexDao, Optional<String> threatSort);
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertRetrieveLatestDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertRetrieveLatestDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertRetrieveLatestDao.java
new file mode 100644
index 0000000..1a0d2a0
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertRetrieveLatestDao.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.dao.metaalert;
+
+import org.apache.metron.indexing.dao.RetrieveLatestDao;
+
+public interface MetaAlertRetrieveLatestDao extends RetrieveLatestDao {
+
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertSearchDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertSearchDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertSearchDao.java
new file mode 100644
index 0000000..e8b9f26
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertSearchDao.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.dao.metaalert;
+
+import org.apache.metron.indexing.dao.search.InvalidSearchException;
+import org.apache.metron.indexing.dao.search.SearchDao;
+import org.apache.metron.indexing.dao.search.SearchResponse;
+
+public interface MetaAlertSearchDao extends SearchDao {
+
+ /**
+ * Given an alert GUID, retrieve all associated meta alerts.
+ * @param guid The alert GUID to be searched for
+ * @return All meta alerts with a child alert having the GUID
+ * @throws InvalidSearchException If a problem occurs with the search
+ */
+ SearchResponse getAllMetaAlertsForAlert(String guid) throws InvalidSearchException;
+
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertUpdateDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertUpdateDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertUpdateDao.java
new file mode 100644
index 0000000..f4374b4
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertUpdateDao.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.dao.metaalert;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.apache.metron.indexing.dao.search.GetRequest;
+import org.apache.metron.indexing.dao.search.InvalidCreateException;
+import org.apache.metron.indexing.dao.update.Document;
+import org.apache.metron.indexing.dao.update.PatchRequest;
+import org.apache.metron.indexing.dao.update.UpdateDao;
+
+public interface MetaAlertUpdateDao extends UpdateDao {
+
+ String STATUS_PATH = "/" + MetaAlertConstants.STATUS_FIELD;
+ String ALERT_PATH = "/" + MetaAlertConstants.ALERT_FIELD;
+
+ /**
+ * Determines if a given patch request is allowed or not. By default patching the 'alert' or
+ * 'status' fields are not allowed, because they should be updated via the specific methods.
+ * @param request The patch request to examine
+ * @return True if patch can be performed, false otherwise
+ */
+ default boolean isPatchAllowed(PatchRequest request) {
+ if (request.getPatch() != null && !request.getPatch().isEmpty()) {
+ for (Map<String, Object> patch : request.getPatch()) {
+ Object pathObj = patch.get("path");
+ if (pathObj != null && pathObj instanceof String) {
+ String path = (String) pathObj;
+ if (STATUS_PATH.equals(path) || ALERT_PATH.equals(path)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Creates a meta alert from a list of child alerts. The most recent version of each child alert is
+ * retrieved using the DAO abstractions.
+ *
+ * @param request A request object containing get requests for alerts to be added and a list of groups
+ * @return A response indicating success or failure along with the GUID of the new meta alert
+ * @throws InvalidCreateException If a malformed create request is provided
+ * @throws IOException If a problem occurs during communication
+ */
+ MetaAlertCreateResponse createMetaAlert(MetaAlertCreateRequest request)
+ throws InvalidCreateException, IOException;
+
+ /**
+ * Adds alerts to a metaalert, based on a list of GetRequests provided for retrieval.
+ * @param metaAlertGuid The GUID of the metaalert to be given new children.
+ * @param alertRequests GetRequests for the appropriate alerts to add.
+ * @return True if metaalert is modified, false otherwise.
+ */
+ boolean addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests)
+ throws IOException;
+
+ /**
+ * Removes alerts from a metaalert
+ * @param metaAlertGuid The metaalert guid to be affected.
+ * @param alertRequests A list of GetReqests that will provide the alerts to remove
+ * @return True if there are updates, false otherwise
+ * @throws IOException If an error is thrown during retrieal.
+ */
+ boolean removeAlertsFromMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests)
+ throws IOException;
+
+ /**
+ * Removes a metaalert link from a given alert. An nonexistent link performs no change.
+ * @param metaAlertGuid The metaalert GUID to link.
+ * @param alert The alert to be linked to.
+ * @return True if the alert changed, false otherwise.
+ */
+ default boolean removeMetaAlertFromAlert(String metaAlertGuid, Document alert) {
+ List<String> metaAlertField = new ArrayList<>();
+ @SuppressWarnings("unchecked")
+ List<String> alertField = (List<String>) alert.getDocument()
+ .get(MetaAlertConstants.METAALERT_FIELD);
+ if (alertField != null) {
+ metaAlertField.addAll(alertField);
+ }
+ boolean metaAlertRemoved = metaAlertField.remove(metaAlertGuid);
+ if (metaAlertRemoved) {
+ alert.getDocument().put(MetaAlertConstants.METAALERT_FIELD, metaAlertField);
+ }
+ return metaAlertRemoved;
+ }
+
+ /**
+ * The meta alert status field can be set to either 'active' or 'inactive' and will control whether or not meta alerts
+ * (and child alerts) appear in search results. An 'active' status will cause meta alerts to appear in search
+ * results instead of it's child alerts and an 'inactive' status will suppress the meta alert from search results
+ * with child alerts appearing in search results as normal. A change to 'inactive' will cause the meta alert GUID to
+ * be removed from all it's child alert's "metaalerts" field. A change back to 'active' will have the opposite effect.
+ *
+ * @param metaAlertGuid The GUID of the meta alert
+ * @param status A status value of 'active' or 'inactive'
+ * @return True or false depending on if the status was changed
+ * @throws IOException if an error occurs during the update.
+ */
+ boolean updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status)
+ throws IOException;
+
+ /**
+ * Adds a metaalert link to a provided alert Document. Adding an existing link does no change.
+ * @param metaAlertGuid The GUID to be added.
+ * @param alert The alert we're adding the link to.
+ * @return True if the alert is modified, false if not.
+ */
+ default boolean addMetaAlertToAlert(String metaAlertGuid, Document alert) {
+ List<String> metaAlertField = new ArrayList<>();
+ @SuppressWarnings("unchecked")
+ List<String> alertField = (List<String>) alert.getDocument()
+ .get(MetaAlertConstants.METAALERT_FIELD);
+ if (alertField != null) {
+ metaAlertField.addAll(alertField);
+ }
+
+ boolean metaAlertAdded = !metaAlertField.contains(metaAlertGuid);
+ if (metaAlertAdded) {
+ metaAlertField.add(metaAlertGuid);
+ alert.getDocument().put(MetaAlertConstants.METAALERT_FIELD, metaAlertField);
+ }
+ return metaAlertAdded;
+ }
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaScores.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaScores.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaScores.java
index 07285d6..55b1aa0 100644
--- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaScores.java
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaScores.java
@@ -18,12 +18,14 @@
package org.apache.metron.indexing.dao.metaalert;
-import org.apache.commons.math3.stat.descriptive.rank.Median;
-
+import java.util.ArrayList;
import java.util.DoubleSummaryStatistics;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.commons.math3.stat.descriptive.rank.Median;
+import org.apache.metron.indexing.dao.update.Document;
+import org.apache.metron.stellar.common.utils.ConversionUtils;
public class MetaScores {
@@ -52,4 +54,50 @@ public class MetaScores {
public Map<String, Object> getMetaScores() {
return metaScores;
}
+
+ /**
+ * Calculate the meta alert scores for a Document. The scores are placed directly in the provided
+ * document.
+ * @param metaAlert The Document containing scores
+ */
+ @SuppressWarnings("unchecked")
+ public static void calculateMetaScores(Document metaAlert, String threatTriageField,
+ String threatSort) {
+ MetaScores metaScores = new MetaScores(new ArrayList<>());
+ List<Object> alertsRaw = ((List<Object>) metaAlert.getDocument()
+ .get(MetaAlertConstants.ALERT_FIELD));
+ if (alertsRaw != null && !alertsRaw.isEmpty()) {
+ ArrayList<Double> scores = new ArrayList<>();
+ for (Object alertRaw : alertsRaw) {
+ Map<String, Object> alert = (Map<String, Object>) alertRaw;
+ Double scoreNum = parseThreatField(alert.get(threatTriageField));
+ if (scoreNum != null) {
+ scores.add(scoreNum);
+ }
+ }
+ metaScores = new MetaScores(scores);
+ }
+
+ // add a summary (max, min, avg, ...) of all the threat scores from the child alerts
+ metaAlert.getDocument().putAll(metaScores.getMetaScores());
+
+ // add the overall threat score for the metaalert; one of the summary aggregations as defined
+ // by `threatSort`
+ Object threatScore = metaScores.getMetaScores().get(threatSort);
+
+ // add the threat score as a float; type needs to match the threat score field from each of
+ // the sensor indices
+ metaAlert.getDocument()
+ .put(threatTriageField, ConversionUtils.convert(threatScore, Float.class));
+ }
+
+ protected static Double parseThreatField(Object threatRaw) {
+ Double threat = null;
+ if (threatRaw instanceof Number) {
+ threat = ((Number) threatRaw).doubleValue();
+ } else if (threatRaw instanceof String) {
+ threat = Double.parseDouble((String) threatRaw);
+ }
+ return threat;
+ }
}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/lucene/AbstractLuceneMetaAlertUpdateDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/lucene/AbstractLuceneMetaAlertUpdateDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/lucene/AbstractLuceneMetaAlertUpdateDao.java
new file mode 100644
index 0000000..b47d648
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/lucene/AbstractLuceneMetaAlertUpdateDao.java
@@ -0,0 +1,334 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.dao.metaalert.lucene;
+
+import static org.apache.metron.common.Constants.GUID;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import org.apache.metron.common.Constants;
+import org.apache.metron.indexing.dao.RetrieveLatestDao;
+import org.apache.metron.indexing.dao.metaalert.MetaAlertConfig;
+import org.apache.metron.indexing.dao.metaalert.MetaAlertConstants;
+import org.apache.metron.indexing.dao.metaalert.MetaAlertRetrieveLatestDao;
+import org.apache.metron.indexing.dao.metaalert.MetaAlertStatus;
+import org.apache.metron.indexing.dao.metaalert.MetaAlertUpdateDao;
+import org.apache.metron.indexing.dao.metaalert.MetaScores;
+import org.apache.metron.indexing.dao.search.GetRequest;
+import org.apache.metron.indexing.dao.update.Document;
+import org.apache.metron.indexing.dao.update.OriginalNotFoundException;
+import org.apache.metron.indexing.dao.update.PatchRequest;
+import org.apache.metron.indexing.dao.update.UpdateDao;
+
+public abstract class AbstractLuceneMetaAlertUpdateDao implements MetaAlertUpdateDao {
+
+ private UpdateDao updateDao;
+ private MetaAlertRetrieveLatestDao retrieveLatestDao;
+ private MetaAlertConfig config;
+
+ protected AbstractLuceneMetaAlertUpdateDao(
+ UpdateDao updateDao,
+ MetaAlertRetrieveLatestDao retrieveLatestDao,
+ MetaAlertConfig config) {
+ this.updateDao = updateDao;
+ this.retrieveLatestDao = retrieveLatestDao;
+ this.config = config;
+ }
+
+ public UpdateDao getUpdateDao() {
+ return updateDao;
+ }
+
+ public MetaAlertRetrieveLatestDao getRetrieveLatestDao() {
+ return retrieveLatestDao;
+ }
+
+ public MetaAlertConfig getConfig() {
+ return config;
+ }
+
+ /**
+ * Performs a patch operation on a document based on the result of @{link #isPatchAllowed(PatchRequest)}
+ *
+ * @param retrieveLatestDao DAO to retrieve the item to be patched
+ * @param request The patch request.
+ * @param timestamp Optionally a timestamp to set. If not specified then current time is used.
+ * @throws OriginalNotFoundException If no original document is found to patch.
+ * @throws IOException If an error occurs performing the patch.
+ */
+ @Override
+ public void patch(RetrieveLatestDao retrieveLatestDao, PatchRequest request,
+ Optional<Long> timestamp)
+ throws OriginalNotFoundException, IOException {
+ if (isPatchAllowed(request)) {
+ updateDao.patch(retrieveLatestDao, request, timestamp);
+ } else {
+ throw new IllegalArgumentException(
+ "Meta alert patches are not allowed for /alert or /status paths. "
+ + "Please use the add/remove alert or update status functions instead.");
+ }
+ }
+
+ @Override
+ public void batchUpdate(Map<Document, Optional<String>> updates) {
+ throw new UnsupportedOperationException("Meta alerts do not allow for bulk updates");
+ }
+
+ /**
+ * Build the Document representing a meta alert to be created.
+ * @param alerts The Elasticsearch results for the meta alerts child documents
+ * @param groups The groups used to create this meta alert
+ * @return A Document representing the new meta alert
+ */
+ protected Document buildCreateDocument(Iterable<Document> alerts, List<String> groups,
+ String alertField) {
+ // Need to create a Document from the multiget. Scores will be calculated later
+ Map<String, Object> metaSource = new HashMap<>();
+ List<Map<String, Object>> alertList = new ArrayList<>();
+ for (Document alert : alerts) {
+ alertList.add(alert.getDocument());
+ }
+ metaSource.put(alertField, alertList);
+
+ // Add any meta fields
+ String guid = UUID.randomUUID().toString();
+ metaSource.put(GUID, guid);
+ metaSource.put(Constants.Fields.TIMESTAMP.getName(), System.currentTimeMillis());
+ metaSource.put(MetaAlertConstants.GROUPS_FIELD, groups);
+ metaSource.put(MetaAlertConstants.STATUS_FIELD, MetaAlertStatus.ACTIVE.getStatusString());
+
+ return new Document(metaSource, guid, MetaAlertConstants.METAALERT_TYPE,
+ System.currentTimeMillis());
+ }
+
+ /**
+ * Builds the set of updates when alerts are removed from a meta alert
+ * @param metaAlert The meta alert to remove alerts from
+ * @param alerts The alert Documents to be removed
+ * @return The updates to be run
+ * @throws IOException If an error is thrown.
+ */
+ @SuppressWarnings("unchecked")
+ protected Map<Document, Optional<String>> buildRemoveAlertsFromMetaAlert(Document metaAlert,
+ Iterable<Document> alerts)
+ throws IOException {
+ Map<Document, Optional<String>> updates = new HashMap<>();
+
+ List<String> alertGuids = new ArrayList<>();
+ for (Document alert : alerts) {
+ alertGuids.add(alert.getGuid());
+ }
+ List<Map<String, Object>> alertsBefore = new ArrayList<>();
+ Map<String, Object> documentBefore = metaAlert.getDocument();
+ if (documentBefore.containsKey(MetaAlertConstants.ALERT_FIELD)) {
+ alertsBefore
+ .addAll((List<Map<String, Object>>) documentBefore.get(MetaAlertConstants.ALERT_FIELD));
+ }
+ boolean metaAlertUpdated = removeAlertsFromMetaAlert(metaAlert, alertGuids);
+ if (metaAlertUpdated) {
+ List<Map<String, Object>> alertsAfter = (List<Map<String, Object>>) metaAlert.getDocument()
+ .get(MetaAlertConstants.ALERT_FIELD);
+ if (alertsAfter.size() < alertsBefore.size() && alertsAfter.size() == 0) {
+ throw new IllegalStateException("Removing these alerts will result in an empty meta alert. Empty meta alerts are not allowed.");
+ }
+ MetaScores
+ .calculateMetaScores(metaAlert, config.getThreatTriageField(), config.getThreatSort());
+ updates.put(metaAlert, Optional.of(config.getMetaAlertIndex()));
+ for (Document alert : alerts) {
+ if (removeMetaAlertFromAlert(metaAlert.getGuid(), alert)) {
+ updates.put(alert, Optional.empty());
+ }
+ }
+ }
+ return updates;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public boolean removeAlertsFromMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests)
+ throws IOException {
+ Document metaAlert = retrieveLatestDao
+ .getLatest(metaAlertGuid, MetaAlertConstants.METAALERT_TYPE);
+ if (metaAlert == null) {
+ return false;
+ }
+ if (MetaAlertStatus.ACTIVE.getStatusString()
+ .equals(metaAlert.getDocument().get(MetaAlertConstants.STATUS_FIELD))) {
+ Iterable<Document> alerts = retrieveLatestDao.getAllLatest(alertRequests);
+ Map<Document, Optional<String>> updates = buildRemoveAlertsFromMetaAlert(metaAlert, alerts);
+ update(updates);
+ return updates.size() != 0;
+ } else {
+ throw new IllegalStateException("Removing alerts from an INACTIVE meta alert is not allowed");
+ }
+ }
+
+ /**
+ * Removes a given set of alerts from a given alert. AlertGuids that are not found are ignored.
+ * @param metaAlert The metaalert to be mutated.
+ * @param alertGuids The alerts to remove from the metaaelrt.
+ * @return True if the metaAlert changed, false otherwise.
+ */
+ protected boolean removeAlertsFromMetaAlert(Document metaAlert, Collection<String> alertGuids) {
+ // If we don't have child alerts or nothing is being removed, immediately return false.
+ if (!metaAlert.getDocument().containsKey(MetaAlertConstants.ALERT_FIELD)
+ || alertGuids.size() == 0) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> currentAlerts = (List<Map<String, Object>>) metaAlert.getDocument()
+ .get(MetaAlertConstants.ALERT_FIELD);
+ int previousSize = currentAlerts.size();
+ // Only remove an alert if it is in the meta alert
+ currentAlerts.removeIf(currentAlert -> alertGuids.contains(currentAlert.get(GUID)));
+ return currentAlerts.size() != previousSize;
+ }
+
+ @Override
+ public boolean updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status)
+ throws IOException {
+ Document metaAlert = retrieveLatestDao
+ .getLatest(metaAlertGuid, MetaAlertConstants.METAALERT_TYPE);
+ String currentStatus = (String) metaAlert.getDocument().get(MetaAlertConstants.STATUS_FIELD);
+ boolean metaAlertUpdated = !status.getStatusString().equals(currentStatus);
+ if (metaAlertUpdated) {
+ List<GetRequest> getRequests = new ArrayList<>();
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> currentAlerts = (List<Map<String, Object>>) metaAlert.getDocument()
+ .get(MetaAlertConstants.ALERT_FIELD);
+ currentAlerts.stream()
+ .forEach(currentAlert -> getRequests.add(new GetRequest((String) currentAlert.get(GUID),
+ (String) currentAlert.get(config.getSourceTypeField()))));
+ Iterable<Document> alerts = retrieveLatestDao.getAllLatest(getRequests);
+ Map<Document, Optional<String>> updates = buildStatusChangeUpdates(metaAlert, alerts, status);
+ update(updates);
+ }
+ return metaAlertUpdated;
+ }
+
+ /**
+ * Given a Metaalert and a status change, builds the set of updates to be run.
+ * @param metaAlert The metaalert to have status changed
+ * @param alerts The alerts to change status for
+ * @param status The status to change to
+ * @return The updates to be run
+ */
+ protected Map<Document, Optional<String>> buildStatusChangeUpdates(Document metaAlert,
+ Iterable<Document> alerts,
+ MetaAlertStatus status) {
+ metaAlert.getDocument().put(MetaAlertConstants.STATUS_FIELD, status.getStatusString());
+
+ Map<Document, Optional<String>> updates = new HashMap<>();
+ updates.put(metaAlert, Optional.of(config.getMetaAlertIndex()));
+
+ for (Document alert : alerts) {
+ boolean metaAlertAdded = false;
+ boolean metaAlertRemoved = false;
+ // If we're making it active add add the meta alert guid for every alert.
+ if (MetaAlertStatus.ACTIVE.equals(status)) {
+ metaAlertAdded = addMetaAlertToAlert(metaAlert.getGuid(), alert);
+ }
+ // If we're making it inactive, remove the meta alert guid from every alert.
+ if (MetaAlertStatus.INACTIVE.equals(status)) {
+ metaAlertRemoved = removeMetaAlertFromAlert(metaAlert.getGuid(), alert);
+ }
+ if (metaAlertAdded || metaAlertRemoved) {
+ updates.put(alert, Optional.empty());
+ }
+ }
+ return updates;
+ }
+
+ /**
+ * Builds the updates to be run based on a given metaalert and a set of new alerts for the it.
+ * @param metaAlert The base metaalert we're building updates for
+ * @param alerts The alerts being added
+ * @return The set of resulting updates.
+ */
+ protected Map<Document, Optional<String>> buildAddAlertToMetaAlertUpdates(Document metaAlert,
+ Iterable<Document> alerts) {
+ Map<Document, Optional<String>> updates = new HashMap<>();
+ boolean metaAlertUpdated = addAlertsToMetaAlert(metaAlert, alerts);
+ if (metaAlertUpdated) {
+ MetaScores
+ .calculateMetaScores(metaAlert, config.getThreatTriageField(), config.getThreatSort());
+ updates.put(metaAlert, Optional.of(config.getMetaAlertIndex()));
+ for (Document alert : alerts) {
+ if (addMetaAlertToAlert(metaAlert.getGuid(), alert)) {
+ updates.put(alert, Optional.empty());
+ }
+ }
+ }
+ return updates;
+ }
+
+ /**
+ * Adds the provided alerts to a given metaalert.
+ * @param metaAlert The metaalert to be given new children.
+ * @param alerts The alerts to be added as children
+ * @return True if metaalert is modified, false otherwise.
+ */
+ protected boolean addAlertsToMetaAlert(Document metaAlert, Iterable<Document> alerts) {
+ boolean alertAdded = false;
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> currentAlerts = (List<Map<String, Object>>) metaAlert.getDocument()
+ .get(MetaAlertConstants.ALERT_FIELD);
+ if (currentAlerts == null) {
+ currentAlerts = new ArrayList<>();
+ metaAlert.getDocument().put(MetaAlertConstants.ALERT_FIELD, currentAlerts);
+ }
+ Set<String> currentAlertGuids = currentAlerts.stream().map(currentAlert ->
+ (String) currentAlert.get(GUID)).collect(Collectors.toSet());
+ for (Document alert : alerts) {
+ String alertGuid = alert.getGuid();
+ // Only add an alert if it isn't already in the meta alert
+ if (!currentAlertGuids.contains(alertGuid)) {
+ currentAlerts.add(alert.getDocument());
+ alertAdded = true;
+ }
+ }
+ return alertAdded;
+ }
+
+ /**
+ * Calls the single update variant if there's only one update, otherwise calls batch.
+ * MetaAlerts may defer to an implementation specific IndexDao.
+ * @param updates The list of updates to run
+ * @throws IOException If there's an update error
+ */
+ protected void update(Map<Document, Optional<String>> updates)
+ throws IOException {
+ if (updates.size() == 1) {
+ Entry<Document, Optional<String>> singleUpdate = updates.entrySet().iterator().next();
+ updateDao.update(singleUpdate.getKey(), singleUpdate.getValue());
+ } else if (updates.size() > 1) {
+ updateDao.batchUpdate(updates);
+ } // else we have no updates, so don't do anything
+ }
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchDao.java
index eee91ae..582f1ef 100644
--- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchDao.java
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchDao.java
@@ -17,18 +17,22 @@
*/
package org.apache.metron.indexing.dao.search;
-import java.io.IOException;
-import java.util.List;
-import org.apache.metron.indexing.dao.update.Document;
-
public interface SearchDao {
+ /**
+ * Return search response based on the search request
+ *
+ * @param searchRequest The request defining the search parameters.
+ * @return A response containing the results of the search.
+ * @throws InvalidSearchException If the search request is malformed.
+ */
SearchResponse search(SearchRequest searchRequest) throws InvalidSearchException;
+ /**
+ * Return group response based on the group request
+ * @param groupRequest The request defining the grouping parameters.
+ * @return A response containing the results of the grouping operation.
+ * @throws InvalidSearchException If the grouping request is malformed.
+ */
GroupResponse group(GroupRequest groupRequest) throws InvalidSearchException;
-
- Document getLatest(String guid, String sensorType) throws IOException;
-
- Iterable<Document> getAllLatest(List<GetRequest> getRequests) throws IOException;
-
}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchResponse.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchResponse.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchResponse.java
index 5b0b006..b4dfab7 100644
--- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchResponse.java
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/SearchResponse.java
@@ -18,7 +18,6 @@
package org.apache.metron.indexing.dao.search;
import com.fasterxml.jackson.annotation.JsonInclude;
-
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -84,4 +83,13 @@ public class SearchResponse {
result = 31 * result + (getFacetCounts() != null ? getFacetCounts().hashCode() : 0);
return result;
}
+
+ @Override
+ public String toString() {
+ return "SearchResponse{" +
+ "total=" + total +
+ ", results=" + results +
+ ", facetCounts=" + facetCounts +
+ '}';
+ }
}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/PatchUtil.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/PatchUtil.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/PatchUtil.java
new file mode 100644
index 0000000..5a4ef27
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/PatchUtil.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.dao.update;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.metron.common.utils.JSONUtils;
+import org.apache.metron.indexing.dao.RetrieveLatestDao;
+
+public class PatchUtil {
+
+ public static Document getPatchedDocument(
+ RetrieveLatestDao retrieveLatestDao,
+ PatchRequest request
+ , Optional<Long> timestamp
+ ) throws OriginalNotFoundException, IOException {
+ Map<String, Object> latest = request.getSource();
+ if (latest == null) {
+ Document latestDoc = retrieveLatestDao.getLatest(request.getGuid(), request.getSensorType());
+ if (latestDoc != null && latestDoc.getDocument() != null) {
+ latest = latestDoc.getDocument();
+ } else {
+ throw new OriginalNotFoundException(
+ "Unable to patch an document that doesn't exist and isn't specified.");
+ }
+ }
+ Map<String, Object> updated = JSONUtils.INSTANCE.applyPatch(request.getPatch(), latest);
+ return new Document(updated
+ , request.getGuid()
+ , request.getSensorType()
+ , timestamp.orElse(System.currentTimeMillis()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/UpdateDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/UpdateDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/UpdateDao.java
index ca21b62..6f136ea 100644
--- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/UpdateDao.java
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/update/UpdateDao.java
@@ -20,11 +20,58 @@ package org.apache.metron.indexing.dao.update;
import java.io.IOException;
import java.util.Map;
import java.util.Optional;
+import org.apache.metron.indexing.dao.RetrieveLatestDao;
public interface UpdateDao {
+ /**
+ * Update a given Document and optionally the index where the document exists. This is a full
+ * update, meaning the current document will be replaced if it exists or a new document will be
+ * created if it does not exist. Partial updates are not supported in this method.
+ *
+ * @param update The document to replace from the index.
+ * @param index The index where the document lives.
+ * @throws IOException If an error occurs during the update.
+ */
void update(Document update, Optional<String> index) throws IOException;
+ /**
+ * Similar to the update method but accepts multiple documents and performs updates in batch.
+ *
+ * @param updates A map of the documents to update to the index where they live.
+ * @throws IOException If an error occurs during the updates.
+ */
void batchUpdate(Map<Document, Optional<String>> updates) throws IOException;
+ /**
+ * Update a document in an index given a JSON Patch (see RFC 6902 at
+ * https://tools.ietf.org/html/rfc6902)
+ * @param request The patch request
+ * @param timestamp Optionally a timestamp to set. If not specified then current time is used.
+ * @throws OriginalNotFoundException If the original is not found, then it cannot be patched.
+ * @throws IOException If an error occurs while patching.
+ */
+ default void patch(RetrieveLatestDao retrieveLatestDao, PatchRequest request
+ , Optional<Long> timestamp
+ ) throws OriginalNotFoundException, IOException {
+ Document d = PatchUtil.getPatchedDocument(retrieveLatestDao, request, timestamp);
+ update(d, Optional.ofNullable(request.getIndex()));
+ }
+
+
+ /**
+ * Replace a document in an index.
+ * @param request The replacement request.
+ * @param timestamp The timestamp (optional) of the update. If not specified, then current time will be used.
+ * @throws IOException If an error occurs during replacement.
+ */
+ default void replace(ReplaceRequest request, Optional<Long> timestamp)
+ throws IOException {
+ Document d = new Document(request.getReplacement(),
+ request.getGuid(),
+ request.getSensorType(),
+ timestamp.orElse(System.currentTimeMillis())
+ );
+ update(d, Optional.ofNullable(request.getIndex()));
+ }
}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/util/IndexingCacheUtil.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/util/IndexingCacheUtil.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/util/IndexingCacheUtil.java
new file mode 100644
index 0000000..3ff3a20
--- /dev/null
+++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/util/IndexingCacheUtil.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.indexing.util;
+
+import java.util.Map;
+import java.util.function.Function;
+import org.apache.metron.common.configuration.IndexingConfigurations;
+import org.apache.metron.common.zookeeper.ConfigurationsCache;
+
+public class IndexingCacheUtil {
+ public static Function<String, String> getIndexLookupFunction(ConfigurationsCache cache) {
+ return sensorType -> {
+ IndexingConfigurations indexingConfigs = cache.get( IndexingConfigurations.class);
+ Map<String, Object> indexingSensorConfigs = indexingConfigs.getSensorIndexingConfig(sensorType);
+ String indexingTopic = (String) indexingSensorConfigs.get(IndexingConfigurations.INDEX_CONF);
+ return indexingTopic != null ? indexingTopic : sensorType;
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/49f851e0/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/InMemoryMetaAlertDao.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/InMemoryMetaAlertDao.java b/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/InMemoryMetaAlertDao.java
index baa5416..803d320 100644
--- a/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/InMemoryMetaAlertDao.java
+++ b/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/InMemoryMetaAlertDao.java
@@ -32,8 +32,10 @@ import java.util.Optional;
import java.util.stream.Collectors;
import org.adrianwalker.multilinestring.Multiline;
import org.apache.metron.common.utils.JSONUtils;
+import org.apache.metron.indexing.dao.metaalert.MetaAlertConstants;
import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateRequest;
import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateResponse;
+import org.apache.metron.indexing.dao.metaalert.MetaAlertDao;
import org.apache.metron.indexing.dao.metaalert.MetaAlertStatus;
import org.apache.metron.indexing.dao.metaalert.MetaScores;
import org.apache.metron.indexing.dao.search.FieldType;
@@ -57,6 +59,7 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
public static Map<String, Collection<String>> METAALERT_STORE = new HashMap<>();
private IndexDao indexDao;
+ private int pageSize = 10;
/**
* {
@@ -96,6 +99,7 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
// Ignore threatSort for test.
}
+
@Override
public Document getLatest(String guid, String sensorType) throws IOException {
return indexDao.getLatest(guid, sensorType);
@@ -112,7 +116,7 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
}
@Override
- public void batchUpdate(Map<Document, Optional<String>> updates) throws IOException {
+ public void batchUpdate(Map<Document, Optional<String>> updates) {
throw new UnsupportedOperationException("InMemoryMetaAlertDao can't do bulk updates");
}
@@ -128,9 +132,10 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
}
@Override
- public void patch(PatchRequest request, Optional<Long> timestamp)
+ public void patch(RetrieveLatestDao retrieveLatestDao, PatchRequest request,
+ Optional<Long> timestamp)
throws OriginalNotFoundException, IOException {
- indexDao.patch(request, timestamp);
+ indexDao.patch(retrieveLatestDao, request, timestamp);
}
@Override
@@ -153,7 +158,7 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
@SuppressWarnings("unchecked")
@Override
public MetaAlertCreateResponse createMetaAlert(MetaAlertCreateRequest request)
- throws InvalidCreateException, IOException {
+ throws InvalidCreateException {
List<GetRequest> alertRequests = request.getAlerts();
if (alertRequests.isEmpty()) {
MetaAlertCreateResponse response = new MetaAlertCreateResponse();
@@ -162,12 +167,13 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
}
// Build meta alert json. Give it a reasonable GUID
JSONObject metaAlert = new JSONObject();
- String metaAlertGuid = "meta_" + (InMemoryDao.BACKING_STORE.get(MetaAlertDao.METAALERTS_INDEX).size() + 1);
+ String metaAlertGuid =
+ "meta_" + (InMemoryDao.BACKING_STORE.get(getMetaAlertIndex()).size() + 1);
metaAlert.put(GUID, metaAlertGuid);
JSONArray groupsArray = new JSONArray();
groupsArray.addAll(request.getGroups());
- metaAlert.put(MetaAlertDao.GROUPS_FIELD, groupsArray);
+ metaAlert.put(MetaAlertConstants.GROUPS_FIELD, groupsArray);
// Retrieve the alert for each guid
// For the purpose of testing, we're just using guids for the alerts field and grabbing the scores.
@@ -183,7 +189,8 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
List<SearchResult> searchResults = searchResponse.getResults();
if (searchResults.size() > 1) {
throw new InvalidCreateException(
- "Found more than one result for: " + alertRequest.getGuid() + ". Values: " + searchResults
+ "Found more than one result for: " + alertRequest.getGuid() + ". Values: "
+ + searchResults
);
}
@@ -191,7 +198,9 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
SearchResult result = searchResults.get(0);
alertArray.add(result.getSource());
Double threatScore = Double
- .parseDouble(result.getSource().getOrDefault(THREAT_FIELD_DEFAULT, "0").toString());
+ .parseDouble(
+ result.getSource().getOrDefault(MetaAlertConstants.THREAT_FIELD_DEFAULT, "0")
+ .toString());
threatScores.add(threatScore);
}
@@ -201,12 +210,12 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
alertGuids.add(alertRequest.getGuid());
}
- metaAlert.put(MetaAlertDao.ALERT_FIELD, alertArray);
+ metaAlert.put(MetaAlertConstants.ALERT_FIELD, alertArray);
metaAlert.putAll(new MetaScores(threatScores).getMetaScores());
- metaAlert.put(STATUS_FIELD, MetaAlertStatus.ACTIVE.getStatusString());
+ metaAlert.put(MetaAlertConstants.STATUS_FIELD, MetaAlertStatus.ACTIVE.getStatusString());
// Add the alert to the store, but make sure not to overwrite existing results
- InMemoryDao.BACKING_STORE.get(MetaAlertDao.METAALERTS_INDEX).add(metaAlert.toJSONString());
+ InMemoryDao.BACKING_STORE.get(getMetaAlertIndex()).add(metaAlert.toJSONString());
METAALERT_STORE.put(metaAlertGuid, new HashSet<>(alertGuids));
@@ -217,12 +226,13 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
}
@Override
- public boolean addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) throws IOException {
+ public boolean addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) {
Collection<String> currentAlertGuids = METAALERT_STORE.get(metaAlertGuid);
if (currentAlertGuids == null) {
return false;
}
- Collection<String> alertGuids = alertRequests.stream().map(GetRequest::getGuid).collect(Collectors.toSet());
+ Collection<String> alertGuids = alertRequests.stream().map(GetRequest::getGuid)
+ .collect(Collectors.toSet());
boolean added = currentAlertGuids.addAll(alertGuids);
if (added) {
METAALERT_STORE.put(metaAlertGuid, currentAlertGuids);
@@ -231,12 +241,13 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
}
@Override
- public boolean removeAlertsFromMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) throws IOException {
+ public boolean removeAlertsFromMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) {
Collection<String> currentAlertGuids = METAALERT_STORE.get(metaAlertGuid);
if (currentAlertGuids == null) {
return false;
}
- Collection<String> alertGuids = alertRequests.stream().map(GetRequest::getGuid).collect(Collectors.toSet());
+ Collection<String> alertGuids = alertRequests.stream().map(GetRequest::getGuid)
+ .collect(Collectors.toSet());
boolean removed = currentAlertGuids.removeAll(alertGuids);
if (removed) {
METAALERT_STORE.put(metaAlertGuid, currentAlertGuids);
@@ -249,16 +260,17 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
public boolean updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status)
throws IOException {
boolean statusChanged = false;
- List<String> metaAlerts = InMemoryDao.BACKING_STORE.get(MetaAlertDao.METAALERTS_INDEX);
- for (String metaAlert: metaAlerts) {
+ List<String> metaAlerts = InMemoryDao.BACKING_STORE.get(getMetaAlertIndex());
+ for (String metaAlert : metaAlerts) {
JSONObject metaAlertJSON = JSONUtils.INSTANCE.load(metaAlert, JSONObject.class);
if (metaAlertGuid.equals(metaAlertJSON.get(GUID))) {
- statusChanged = !status.getStatusString().equals(metaAlertJSON.get(STATUS_FIELD));
+ statusChanged = !status.getStatusString()
+ .equals(metaAlertJSON.get(MetaAlertConstants.STATUS_FIELD));
if (statusChanged) {
- metaAlertJSON.put(STATUS_FIELD, status.getStatusString());
+ metaAlertJSON.put(MetaAlertConstants.STATUS_FIELD, status.getStatusString());
metaAlerts.remove(metaAlert);
metaAlerts.add(metaAlertJSON.toJSONString());
- InMemoryDao.BACKING_STORE.put(MetaAlertDao.METAALERTS_INDEX, metaAlerts);
+ InMemoryDao.BACKING_STORE.put(getMetaAlertIndex(), metaAlerts);
}
break;
}
@@ -266,9 +278,24 @@ public class InMemoryMetaAlertDao implements MetaAlertDao {
return statusChanged;
}
+ public int getPageSize() {
+ return pageSize;
+ }
+
+ public void setPageSize(int pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ public String getMetAlertSensorName() {
+ return MetaAlertConstants.METAALERT_TYPE;
+ }
+
+ public String getMetaAlertIndex() {
+ return "metaalert_index";
+ }
+
public static void clear() {
InMemoryDao.clear();
METAALERT_STORE.clear();
}
-
}