/** * 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()); }
/** * 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; }
@ApiOperation(value = "Updates the status of a meta alert to either 'ACTIVE' or 'INACTIVE'.") @ApiResponse(message = "Returns the complete metaalert document with the updated status.", code = 200) @RequestMapping(value = "/update/status/{guid}/{status}", method = RequestMethod.POST) ResponseEntity<Document> updateMetaAlertStatus( final @ApiParam(name = "guid", value = "Meta alert GUID", required = true) @PathVariable String guid, final @ApiParam(name = "status", value = "Meta alert status with a value of either 'ACTIVE' or 'INACTIVE'", required = true) @PathVariable String status) throws RestException { return new ResponseEntity<>(metaAlertService.updateMetaAlertStatus(guid, MetaAlertStatus.valueOf(status.toUpperCase())), HttpStatus.OK); } }
protected List<Map<String, Object>> buildMetaAlerts(int count, MetaAlertStatus status, Optional<List<Map<String, Object>>> alerts) { List<Map<String, Object>> inputData = new ArrayList<>(); for (int i = 0; i < count; ++i) { final String guid = "meta_" + status.getStatusString() + "_" + i; inputData.add(buildMetaAlert(guid, status, alerts)); } return inputData; }
/** * 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 The updated metaalert with alerts added. */ @Override public Document addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) throws IOException { Document metaAlert = retrieveLatestDao .getLatest(metaAlertGuid, MetaAlertConstants.METAALERT_TYPE); if (metaAlert == null) { throw new IOException(String.format("Unable to add alerts to meta alert. Meta alert with guid %s cannot be found.", metaAlertGuid)); } if (MetaAlertStatus.ACTIVE.getStatusString() .equals(metaAlert.getDocument().get(MetaAlertConstants.STATUS_FIELD))) { Iterable<Document> alerts = retrieveLatestDao.getAllLatest(alertRequests); Set<String> missingAlerts = getMissingAlerts(alertRequests, alerts); if (!missingAlerts.isEmpty()) { throw new IOException(String.format("Unable to add alerts to meta alert. Alert with guid %s cannot be found.", missingAlerts.iterator().next())); } Map<Document, Optional<String>> updates = buildAddAlertToMetaAlertUpdates(metaAlert, alerts); update(updates); return metaAlert; } else { throw new IllegalStateException("Adding alerts to an INACTIVE meta alert is not allowed"); } }
@Override public Document updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) throws IOException { Document metaAlert = retrieveLatestDao .getLatest(metaAlertGuid, MetaAlertConstants.METAALERT_TYPE); if (metaAlert == null) { throw new IOException(String.format("Unable to update meta alert status. Meta alert with guid %s cannot be found.", metaAlertGuid)); } 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 metaAlert; }
metaAlertGuid)); if (MetaAlertStatus.ACTIVE.getStatusString() .equals(metaAlert.getDocument().get(MetaAlertConstants.STATUS_FIELD))) { Iterable<Document> alerts = retrieveLatestDao.getAllLatest(alertRequests);
protected Map<String, Object> buildMetaAlert(String guid, MetaAlertStatus status, Optional<List<Map<String, Object>>> alerts) { Map<String, Object> metaAlert = new HashMap<>(); metaAlert.put(Constants.GUID, guid); metaAlert.put(getSourceTypeField(), METAALERT_TYPE); metaAlert.put(STATUS_FIELD, status.getStatusString()); metaAlert.put(getThreatTriageField(), 100.0d); if (alerts.isPresent()) { List<Map<String, Object>> alertsList = alerts.get(); metaAlert.put(ALERT_FIELD, alertsList); } return metaAlert; }
@Override public Document addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) throws IOException, IllegalStateException { Document metaAlert = getRetrieveLatestDao() .getLatest(metaAlertGuid, MetaAlertConstants.METAALERT_TYPE); if (MetaAlertStatus.ACTIVE.getStatusString() .equals(metaAlert.getDocument().get(MetaAlertConstants.STATUS_FIELD))) { Iterable<Document> alerts = getRetrieveLatestDao().getAllLatest(alertRequests); Map<Document, Optional<String>> updates = buildAddAlertToMetaAlertUpdates(metaAlert, alerts); update(updates); } else { throw new IllegalStateException("Adding alerts to an INACTIVE meta alert is not allowed"); } try { solrClient.commit(METAALERTS_COLLECTION); } catch (SolrServerException e) { throw new IOException("Unable to commit alerts to metaalert: " + metaAlertGuid, e); } return metaAlert; } }
@Test(expected = IllegalStateException.class) public void testRemoveAlertsFromMetaAlertInactive() throws IOException { dao.removeAlertsFromMetaAlert(INACTIVE.getStatusString(), null); }
MetaAlertConstants.STATUS_FIELD + ":" + MetaAlertStatus.ACTIVE.getStatusString();
metaAlertMap.put(ALERT_FIELD, getRawMaps(alerts)); metaAlertMap.put(Constants.GUID, METAALERT_GUID); metaAlertMap.put(STATUS_FIELD, MetaAlertStatus.ACTIVE.getStatusString()); Document metaDoc = new Document( metaAlertMap, expectedMetaAlertMap.put(Constants.GUID, METAALERT_GUID); expectedMetaAlertMap.put(ALERT_FIELD, expectedAlerts); expectedMetaAlertMap.put(STATUS_FIELD, MetaAlertStatus.INACTIVE.getStatusString()); Document expectedMetaAlertDoc = new Document(expectedMetaAlertMap, METAALERT_GUID, METAALERT_TYPE,
metaAlertMap.put(ALERT_FIELD, getRawMaps(alerts)); metaAlertMap.put(Constants.GUID, METAALERT_GUID); metaAlertMap.put(STATUS_FIELD, MetaAlertStatus.INACTIVE.getStatusString()); Document metaDoc = new Document( metaAlertMap, expectedMetaAlertMap.put(ALERT_FIELD, expectedAlerts); expectedMetaAlertMap.put(Constants.GUID, METAALERT_GUID); expectedMetaAlertMap.put(STATUS_FIELD, MetaAlertStatus.ACTIVE.getStatusString()); Document expectedMetaAlertDoc = new Document( expectedMetaAlertMap,
MetaAlertStatus.ACTIVE.getStatusString(), actualDocument.get(STATUS_FIELD) );
@Test public void testRemoveAlertsFromMetaAlertEmptyRemoveMultiple() { Document metDoc = new Document(new HashMap<>(), METAALERT_GUID, METAALERT_TYPE, 0L); metDoc.getDocument().put(STATUS_FIELD, ACTIVE.getStatusString()); List<Document> alerts = buildChildAlerts(3, null, null); metDoc.getDocument().put(ALERT_FIELD, getRawMaps(alerts)); List<String> removeGuids = new ArrayList<>(); removeGuids.add("child_0"); removeGuids.add("child_2"); removeGuids.add("child_doesn't_exist"); boolean actual = dao.removeAlertsFromMetaAlert(metDoc, removeGuids); // Build the expected metaalert Document expected = new Document(new HashMap<>(), METAALERT_GUID, METAALERT_TYPE, 0L); expected.getDocument().put(STATUS_FIELD, ACTIVE.getStatusString()); List<Map<String, Object>> alertsExpected = new ArrayList<>(); alertsExpected.add(new HashMap<String, Object>() {{ put(METAALERT_FIELD, new ArrayList<>()); put(Constants.GUID, "child_1"); put(THREAT_FIELD_DEFAULT, 0.0f); }} ); expected.getDocument().put(ALERT_FIELD, alertsExpected); assertEquals(expected, metDoc); assertTrue(actual); }
@Test public void testRemoveAlertsFromMetaAlertEmptyRemoveList() { Document metaDoc = new Document( new HashMap<>(), METAALERT_GUID, METAALERT_TYPE, 0L ); metaDoc.getDocument().put( STATUS_FIELD, ACTIVE.getStatusString() ); metaDoc.getDocument().put( ALERT_FIELD, new HashMap<String, Object>() {{ put(Constants.GUID, "child_0"); }} ); boolean actual = dao.removeAlertsFromMetaAlert(metaDoc, new ArrayList<>()); assertFalse(actual); }
MetaAlertConstants.STATUS_FIELD + ":" + MetaAlertStatus.ACTIVE.getStatusString(); String guidClause = Constants.GUID + ":" + guid; String fullClause = "{!parent which=" + activeClause + "}" + guidClause;
metaDoc.getDocument().put( STATUS_FIELD, ACTIVE.getStatusString() ); List<Map<String, Object>> alerts = new ArrayList<>(); expected.getDocument().put( STATUS_FIELD, ACTIVE.getStatusString() ); expected.getDocument().put(ALERT_FIELD, new ArrayList<>());
@Override public SearchResponse getAllMetaAlertsForAlert(String guid) throws InvalidSearchException, IOException { if (guid == null || guid.trim().isEmpty()) { throw new InvalidSearchException("Guid cannot be empty"); } // Searches for all alerts containing the meta alert guid in it's "metalerts" array QueryBuilder qb = boolQuery() .must( nestedQuery( MetaAlertConstants.ALERT_FIELD, boolQuery() .must(termQuery(MetaAlertConstants.ALERT_FIELD + "." + GUID, guid)), ScoreMode.None ).innerHit(new InnerHitBuilder()) ) .must(termQuery(MetaAlertConstants.STATUS_FIELD, MetaAlertStatus.ACTIVE.getStatusString())); return queryAllResults(elasticsearchDao.getClient().getHighLevelClient(), qb, config.getMetaAlertIndex(), pageSize); } }
Assert.assertEquals(MetaAlertStatus.ACTIVE.getStatusString(), searchResponse.getResults().get(0).getSource().get(STATUS_FIELD));