You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by ot...@apache.org on 2018/10/24 15:04:08 UTC
[19/51] [abbrv] metron git commit: METRON-1794 Include User Details
When Escalating Alerts (nickwallen) closes apache/metron#1212
METRON-1794 Include User Details When Escalating Alerts (nickwallen) closes apache/metron#1212
Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/c0fb2625
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/c0fb2625
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/c0fb2625
Branch: refs/heads/feature/METRON-1090-stellar-assignment
Commit: c0fb26258f9a78d375a50dd5d746404130dfe06b
Parents: 9c9e295
Author: nickwallen <ni...@nickallen.org>
Authored: Mon Oct 1 09:49:17 2018 -0400
Committer: nickallen <ni...@apache.org>
Committed: Mon Oct 1 09:49:17 2018 -0400
----------------------------------------------------------------------
.../apache/metron/rest/MetronRestConstants.java | 3 +
.../rest/service/impl/AlertsUIServiceImpl.java | 53 ++++++++++++----
.../service/impl/AlertsUIServiceImplTest.java | 63 ++++++++++++++++----
.../src/test/resources/log4j.properties | 5 +-
4 files changed, 98 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/metron/blob/c0fb2625/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java
index e3bf698..94e8e35 100644
--- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java
+++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java
@@ -53,6 +53,9 @@ public class MetronRestConstants {
public static final String KAFKA_BROKER_URL_SPRING_PROPERTY = "kafka.broker.url";
public static final String KAFKA_TOPICS_ESCALATION_PROPERTY = "kafka.topics.escalation";
+ public static final String METRON_ESCALATION_USER_FIELD = "metron_escalation_user";
+ public static final String METRON_ESCALATION_TIMESTAMP_FIELD = "metron_escalation_timestamp";
+
public static final String KERBEROS_ENABLED_SPRING_PROPERTY = "kerberos.enabled";
public static final String KERBEROS_PRINCIPLE_SPRING_PROPERTY = "kerberos.principal";
public static final String KERBEROS_KEYTAB_SPRING_PROPERTY = "kerberos.keytab";
http://git-wip-us.apache.org/repos/asf/metron/blob/c0fb2625/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/AlertsUIServiceImpl.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/AlertsUIServiceImpl.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/AlertsUIServiceImpl.java
index 7d0a8f8..bf035e2 100644
--- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/AlertsUIServiceImpl.java
+++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/AlertsUIServiceImpl.java
@@ -19,26 +19,32 @@ package org.apache.metron.rest.service.impl;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.metron.common.system.Clock;
import org.apache.metron.common.utils.JSONUtils;
-import org.apache.metron.rest.MetronRestConstants;
+import org.apache.metron.hbase.client.UserSettingsClient;
import org.apache.metron.rest.RestException;
import org.apache.metron.rest.model.AlertsUIUserSettings;
-import org.apache.metron.hbase.client.UserSettingsClient;
import org.apache.metron.rest.security.SecurityUtils;
import org.apache.metron.rest.service.AlertsUIService;
import org.apache.metron.rest.service.KafkaService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.apache.metron.rest.MetronRestConstants.KAFKA_TOPICS_ESCALATION_PROPERTY;
+import static org.apache.metron.rest.MetronRestConstants.METRON_ESCALATION_TIMESTAMP_FIELD;
+import static org.apache.metron.rest.MetronRestConstants.METRON_ESCALATION_USER_FIELD;
+
/**
* The default service layer implementation of {@link AlertsUIService}.
*
@@ -47,6 +53,7 @@ import org.springframework.stereotype.Service;
@Service
public class AlertsUIServiceImpl implements AlertsUIService {
+ static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public static final String ALERT_USER_SETTING_TYPE = "metron-alerts-ui";
public static ThreadLocal<ObjectMapper> _mapper = ThreadLocal.withInitial(() ->
new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL));
@@ -54,6 +61,7 @@ public class AlertsUIServiceImpl implements AlertsUIService {
private Environment environment;
private final KafkaService kafkaService;
private UserSettingsClient userSettingsClient;
+ private Clock clock;
@Autowired
public AlertsUIServiceImpl(final KafkaService kafkaService,
@@ -62,15 +70,25 @@ public class AlertsUIServiceImpl implements AlertsUIService {
this.kafkaService = kafkaService;
this.environment = environment;
this.userSettingsClient = userSettingsClient;
+ this.clock = new Clock();
}
@Override
public void escalateAlerts(List<Map<String, Object>> alerts) throws RestException {
+ String user = SecurityUtils.getCurrentUser();
+ String topic = environment.getProperty(KAFKA_TOPICS_ESCALATION_PROPERTY);
+ Long now = clock.currentTimeMillis();
+ LOG.info("Escalating {} alert(s): user={}, topic={}, timestamp={}", alerts.size(), user, topic, now);
+
try {
for (Map<String, Object> alert : alerts) {
- kafkaService.produceMessage(
- environment.getProperty(MetronRestConstants.KAFKA_TOPICS_ESCALATION_PROPERTY),
- JSONUtils.INSTANCE.toJSON(alert, false));
+ // attribute the escalation to the current user
+ alert.put(METRON_ESCALATION_USER_FIELD, user);
+ alert.put(METRON_ESCALATION_TIMESTAMP_FIELD, now);
+
+ // serialize the alert and push it to the escalation topic
+ String message = JSONUtils.INSTANCE.toJSON(alert, false);
+ kafkaService.produceMessage(topic, message);
}
} catch (JsonProcessingException e) {
throw new RestException(e);
@@ -128,4 +146,15 @@ public class AlertsUIServiceImpl implements AlertsUIService {
}
return success;
}
+
+ /**
+ * Set the {@link Clock} used by this service.
+ *
+ * <p>Calling this method is only needed to override the default behavior. This is useful when testing.
+ *
+ * @param clock
+ */
+ public void setClock(Clock clock) {
+ this.clock = clock;
+ }
}
http://git-wip-us.apache.org/repos/asf/metron/blob/c0fb2625/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/AlertsUIServiceImplTest.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/AlertsUIServiceImplTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/AlertsUIServiceImplTest.java
index dc52712..545d7f9 100644
--- a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/AlertsUIServiceImplTest.java
+++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/AlertsUIServiceImplTest.java
@@ -41,6 +41,7 @@ import java.util.Optional;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.adrianwalker.multilinestring.Multiline;
+import org.apache.metron.common.system.FakeClock;
import org.apache.metron.rest.MetronRestConstants;
import org.apache.metron.rest.model.AlertsUIUserSettings;
import org.apache.metron.hbase.client.UserSettingsClient;
@@ -79,9 +80,10 @@ public class AlertsUIServiceImplTest {
private KafkaService kafkaService;
private Environment environment;
private UserSettingsClient userSettingsClient;
- private AlertsUIService alertsUIService;
+ private AlertsUIServiceImpl alertsUIService;
private String user1 = "user1";
private String user2 = "user2";
+ private FakeClock clock;
@SuppressWarnings("unchecked")
@Before
@@ -91,6 +93,11 @@ public class AlertsUIServiceImplTest {
userSettingsClient = mock(UserSettingsClient.class);
alertsUIService = new AlertsUIServiceImpl(kafkaService, environment, userSettingsClient);
+ // use a fake clock for testing
+ clock = new FakeClock();
+ clock.elapseSeconds(1000);
+ alertsUIService.setClock(clock);
+
// assume user1 is logged in for tests
Authentication authentication = Mockito.mock(Authentication.class);
UserDetails userDetails = Mockito.mock(UserDetails.class);
@@ -100,21 +107,26 @@ public class AlertsUIServiceImplTest {
}
@Test
- public void produceMessageShouldProperlyProduceMessage() throws Exception {
- String escalationTopic = "escalation";
- final Map<String, Object> message1 = new HashMap<>();
- message1.put("field", "value1");
- final Map<String, Object> message2 = new HashMap<>();
- message2.put("field", "value2");
- List<Map<String, Object>> messages = Arrays.asList(message1, message2);
+ public void escalateAlertShouldSendMessageToKafka() throws Exception {
+ final String field = "field";
+ final String value1 = "value1";
+ final String value2 = "value2";
+
+ // define the escalation topic
+ final String escalationTopic = "escalation";
when(environment.getProperty(MetronRestConstants.KAFKA_TOPICS_ESCALATION_PROPERTY)).thenReturn(escalationTopic);
- alertsUIService.escalateAlerts(messages);
+ // create an alert along with the expected escalation message that is sent to kafka
+ final Map<String, Object> alert1 = mapOf(field, value1);
+ String escalationMessage1 = escalationMessage(field, value1, user1, clock.currentTimeMillis());
+
+ final Map<String, Object> alert2 = mapOf(field, value2);
+ String escalationMessage2 = escalationMessage(field, value2, user1, clock.currentTimeMillis());
- String expectedMessage1 = "{\"field\":\"value1\"}";
- String expectedMessage2 = "{\"field\":\"value2\"}";
- verify(kafkaService).produceMessage("escalation", expectedMessage1);
- verify(kafkaService).produceMessage("escalation", expectedMessage2);
+ // escalate the alerts and validate
+ alertsUIService.escalateAlerts(Arrays.asList(alert1, alert2));
+ verify(kafkaService).produceMessage(escalationTopic, escalationMessage1);
+ verify(kafkaService).produceMessage(escalationTopic, escalationMessage2);
verifyZeroInteractions(kafkaService);
}
@@ -177,4 +189,29 @@ public class AlertsUIServiceImplTest {
verify(userSettingsClient, times(2)).delete(user1, AlertsUIServiceImpl.ALERT_USER_SETTING_TYPE);
verifyNoMoreInteractions(userSettingsClient);
}
+
+ /**
+ * Defines what the message sent to Kafka should look-like when an alert is escalated.
+ *
+ * @param field The field name.
+ * @param value The value of the field.
+ * @param user The user who escalated the alert.
+ * @param timestamp When the alert was escalated.
+ * @return The escalated message.
+ */
+ private String escalationMessage(String field, String value, String user, Long timestamp) {
+ return String.format("{\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":%d}",
+ field,
+ value,
+ MetronRestConstants.METRON_ESCALATION_USER_FIELD,
+ user,
+ MetronRestConstants.METRON_ESCALATION_TIMESTAMP_FIELD,
+ timestamp);
+ }
+
+ private Map<String, Object> mapOf(String key, Object value) {
+ Map<String, Object> map = new HashMap<>();
+ map.put(key, value);
+ return map;
+ }
}
http://git-wip-us.apache.org/repos/asf/metron/blob/c0fb2625/metron-interface/metron-rest/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/resources/log4j.properties b/metron-interface/metron-rest/src/test/resources/log4j.properties
index 492cecf..edf866e 100644
--- a/metron-interface/metron-rest/src/test/resources/log4j.properties
+++ b/metron-interface/metron-rest/src/test/resources/log4j.properties
@@ -13,4 +13,7 @@
log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd'T'HH:mm:ss.SSS} %-5p [%c] - %m%n
\ No newline at end of file
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd'T'HH:mm:ss.SSS} %-5p [%c] - %m%n
+
+# uncomment the following line to enable debug
+#log4j.logger.org.apache.metron.rest=DEBUG