Siembol alerting: adding javadoc comments (#797)

* adding javadoc for alerting core

* add alerting compiler docs

* minor fixes

* fixing javadoc tag

* adding alerting-storm and alerting-spark javadoc

* minor fixes

* fixes based on review
This commit is contained in:
Marian Novotny
2022-11-02 16:01:50 +00:00
committed by GitHub
parent fd9f7b08ed
commit 14535ecf6b
55 changed files with 1503 additions and 96 deletions

View File

@@ -1,7 +1,15 @@
package uk.co.gresearch.siembol.alerts.common;
import java.util.List;
import java.util.Map;
/**
* An object that collects attributes that can be returned by alerting components
*
* <p>This bean object collects attributes and it is included in an Alerting result object.
*
* @author Marian Novotny
* @see AlertingResult
*
*/
public class AlertingAttributes {
private EvaluationResult evaluationResult;
private String exception;

View File

@@ -4,12 +4,33 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import java.util.Map;
import java.util.*;
/**
* An object that evaluates events using its internal state including rules
*
* <p>This interface has two main implementations for evaluating events using
* standard and correlation rules.
*
*
* @author Marian Novotny
* @see uk.co.gresearch.siembol.alerts.engine.AlertingEngineImpl
* @see uk.co.gresearch.siembol.alerts.correlationengine.CorrelationEngineImpl
* @see CompositeAlertingEngine
*
*/
public interface AlertingEngine {
ObjectReader JSON_READER = new ObjectMapper()
.readerFor(new TypeReference<Map<String, Object>>() { });
/**
* Evaluates event and returns alerting result with a matching result and additional attributes
*
* @param event serialized event as json string
* @return alerting result after evaluation
* @see AlertingResult
*/
default AlertingResult evaluate(String event) {
try {
Map<String, Object> eventMap = JSON_READER.readValue(event);
@@ -19,9 +40,25 @@ public interface AlertingEngine {
}
}
/**
* Evaluates event and returns alerting result with a matching result and additional attributes
*
* @param event deserialized event as map of string to object
* @return alerting result after evaluation
* @see AlertingResult
*/
AlertingResult evaluate(Map<String, Object> event);
/**
* Returns an alerting engine type
*
* @return alerting engine type
* @see AlertingEngineType
*/
AlertingEngineType getAlertingEngineType();
/**
* Removes unused old internal state.
*/
default void clean() {}
}

View File

@@ -1,7 +1,14 @@
package uk.co.gresearch.siembol.alerts.common;
import java.io.Serializable;
/**
* An enum of alerting engine types
*
* @author Marian Novotny
* @see #SIEMBOL_ALERTS
* @see #SIEMBOL_CORRELATION_ALERTS
*
*/
public enum AlertingEngineType implements Serializable {
SIEMBOL_ALERTS("siembol_alerts"),
SIEMBOL_CORRELATION_ALERTS("siembol_correlation_alerts");

View File

@@ -2,7 +2,19 @@ package uk.co.gresearch.siembol.alerts.common;
import java.util.HashMap;
import java.util.Map;
/**
* An enum of fields that can be added into the event after matching the rule
*
* @author Marian Novotny
* @see #FULL_RULE_NAME
* @see #RULE_NAME
* @see #MAX_PER_HOUR_FIELD
* @see #MAX_PER_DAY_FIELD
* @see #EXCEPTION
* @see #PROCESSING_TIME
* @see #CORRELATED_ALERTS
*
*/
public enum AlertingFields {
FULL_RULE_NAME("full_rule_name"),
RULE_NAME("rule_name"),

View File

@@ -3,7 +3,14 @@ package uk.co.gresearch.siembol.alerts.common;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.util.Map;
/**
* An object that combines alerting result status with attributes
*
* @author Marian Novotny
* @see StatusCode
* @see AlertingAttributes
*
*/
public class AlertingResult {
public enum StatusCode {
OK,

View File

@@ -1,5 +1,16 @@
package uk.co.gresearch.siembol.alerts.common;
/**
* An enum of matching results returned in AlertingResult after engine evaluation of an event.
*
* @author Marian Novotny
* @see #DETECTION_SOURCE_TAG_NAME
* @see #DETECTION_SOURCE_TAG_VALUE
* @see #CORRELATION_ENGINE_DETECTION_SOURCE_TAG_VALUE
* @see #CORRELATION_KEY_TAG_NAME
* @see #CORRELATION_ALERT_VISIBLE_TAG_NAME
* @see #TAG_TRUE_VALUE
*
*/
public enum AlertingTags {
DETECTION_SOURCE_TAG_NAME("detection_source"),
DETECTION_SOURCE_TAG_VALUE("siembol_alerts"),

View File

@@ -5,14 +5,37 @@ import java.util.List;
import java.util.Map;
import static uk.co.gresearch.siembol.alerts.common.AlertingResult.StatusCode.OK;
/**
* An object that combines of multiple alerting engines of the same type
*
* <p>This object implements AlertingEngine interface by combining list of AlertingEngine objects.
*
* @author Marian Novotny
* @see AlertingEngine
* @see uk.co.gresearch.siembol.alerts.correlationengine.CorrelationEngineImpl
* @see CompositeAlertingEngine
*
*/
public class CompositeAlertingEngine implements AlertingEngine {
private final List<AlertingEngine> alertingEngines;
/**
* Creates the composite alerting engine by using the list of already created alerting engines.
*
* @param alertingEngines List of underlying alerting engines
*/
public CompositeAlertingEngine(List<AlertingEngine> alertingEngines) {
this.alertingEngines = alertingEngines;
}
/**
* Evaluates an event by underlying alerting engines and
* returns alerting result with a matching result and additional attributes.
*
* @param event serialized event as json string
* @return alerting result after evaluation
* @see AlertingResult
*/
@Override
public AlertingResult evaluate(Map<String, Object> event) {
List<Map<String, Object>> outputEvents = new ArrayList<>();
@@ -39,6 +62,12 @@ public class CompositeAlertingEngine implements AlertingEngine {
return new AlertingResult(OK, attributes);
}
/**
* Returns an alerting engine type of underlying alerting engines
*
* @return alerting engine type
* @see AlertingEngineType
*/
@Override
public AlertingEngineType getAlertingEngineType() {
return alertingEngines.get(0).getAlertingEngineType();

View File

@@ -1,9 +1,29 @@
package uk.co.gresearch.siembol.alerts.common;
/**
* An enum of matching results returned in AlertingResult after engine evaluation of an event.
*
* @author Marian Novotny
* @see #MATCH
* @see #NO_MATCH
*
*/
public enum EvaluationResult {
/*
* The event matched during the evaluation.
*/
MATCH,
/*
* The event not matched during the evaluation.
*/
NO_MATCH;
/**
* Returns negated evaluation result
*
* @param result evaluation result to be negated
* @return negated evaluation result
*/
public static EvaluationResult negate(EvaluationResult result) {
return result == MATCH ? NO_MATCH : MATCH;
}

View File

@@ -14,10 +14,39 @@ import java.util.ArrayList;
import java.util.List;
import static uk.co.gresearch.siembol.alerts.common.AlertingResult.StatusCode.OK;
/**
* An object that validates, tests and compiles alerting rules
*
* <p>This interface provides functionality for validating, testing and compiling alerting rules.
* Moreover, it computes and provides json schema for alerting rules.
*
*
* @author Marian Novotny
* @see AlertingRulesCompiler
* @see AlertingCorrelationRulesCompiler
*
*/
public interface AlertingCompiler {
/**
* Compiles rules into alerting engine
*
* @param rules json string with alerting rules
* @param logger logger for debugging
* @return alerting result with alerting engine
* @see AlertingResult
* @see AlertingEngine
*/
AlertingResult compile(String rules, TestingLogger logger);
/**
* Compiles list of rules into alerting engine
*
* @param rulesList list of json strings with alerting rules
* @param logger logger for debugging
* @return alerting result with alerting engines
* @see AlertingResult
* @see AlertingEngine
*/
default AlertingResult compile(List<String> rulesList, TestingLogger logger) {
if (rulesList.size() == 1) {
return compile(rulesList.get(0), logger);
@@ -37,43 +66,43 @@ public interface AlertingCompiler {
return new AlertingResult(OK, attributes);
}
/**
* Provides json schema validator for alerting rules
*
* @return json schema validator for alerting rules
* @see JsonSchemaValidator
*
*/
JsonSchemaValidator getSchemaValidator();
/**
* Wraps an alerting rule into json rules structure
*
* @param rule json string with alerting rule
* @return json string with rules that contain the rule on input
* @throws IOException if rule is not valid json alerting rule
*
*/
String wrapRuleToRules(String rule) throws IOException;
/**
* Compiles rules into alerting engine and evaluates an event using the engine
*
* @param rules json string with alerting rules
* @param event json string for evaluation
* @return alerting result with testing result
* @see AlertingResult
*/
AlertingResult testRules(String rules, String event);
default AlertingResult compile(String rules) {
return compile(rules, new InactiveTestingLogger());
}
default AlertingResult compile(List<String> rulesList) {
return compile(rulesList, new InactiveTestingLogger());
}
default AlertingResult getSchema() {
AlertingAttributes attributes = new AlertingAttributes();
attributes.setRulesSchema(getSchemaValidator().getJsonSchema().getAttributes().getJsonSchema());
return new AlertingResult(OK, attributes);
}
default AlertingResult validateRule(String rule) {
try {
String rules = wrapRuleToRules(rule);
return validateRules(rules);
} catch (Exception e) {
return AlertingResult.fromException(e);
}
}
default AlertingResult validateRules(String rules) {
try {
return compile(rules);
} catch (Exception e) {
return AlertingResult.fromException(e);
}
}
/**
* Compiles a rule into alerting engine and evaluates an event using the engine
*
* @param rule json string with an alerting rule
* @param event json string for evaluation
* @return alerting result with testing result
* @see AlertingResult
*/
default AlertingResult testRule(String rule, String event) {
try {
String rules = wrapRuleToRules(rule);
@@ -83,6 +112,81 @@ public interface AlertingCompiler {
}
}
/**
* Compiles rules into alerting engine
*
* @param rules json string with alerting rules
* @return alerting result with alerting engine
* @see AlertingResult
* @see AlertingEngine
*/
default AlertingResult compile(String rules) {
return compile(rules, new InactiveTestingLogger());
}
/**
* Compiles list of rules into alerting engine
*
* @param rulesList list of json strings with alerting rules
* @return alerting result with alerting engines
* @see AlertingResult
* @see AlertingEngine
*/
default AlertingResult compile(List<String> rulesList) {
return compile(rulesList, new InactiveTestingLogger());
}
/**
* Provides json schema for alerting rules
*
* @return AlertingResult with json schema for alerting rules
* @see AlertingResult
*
*/
default AlertingResult getSchema() {
AlertingAttributes attributes = new AlertingAttributes();
attributes.setRulesSchema(getSchemaValidator().getJsonSchema().getAttributes().getJsonSchema());
return new AlertingResult(OK, attributes);
}
/**
* Validates rule by trying to compile them
*
* @param rule json string with an alerting rule
* @return alerting result with status OK if the rule was able to compile
* @see AlertingResult
*/
default AlertingResult validateRule(String rule) {
try {
String rules = wrapRuleToRules(rule);
return validateRules(rules);
} catch (Exception e) {
return AlertingResult.fromException(e);
}
}
/**
* Validates rules by trying to compile them
*
* @param rules json string with alerting rules
* @return alerting result with status OK if rules were able to compile
* @see AlertingResult
*/
default AlertingResult validateRules(String rules) {
try {
return compile(rules);
} catch (Exception e) {
return AlertingResult.fromException(e);
}
}
/**
* Validates syntax of rules using json schema validator
*
* @param rules json string with alerting rules
* @return alerting result with status OK if rules have valid syntax
* @see AlertingResult
*/
default AlertingResult validateRulesSyntax(String rules) {
try {
SiembolResult validationResult = getSchemaValidator().validate(rules);

View File

@@ -21,6 +21,17 @@ import java.util.List;
import java.util.stream.Collectors;
import static uk.co.gresearch.siembol.alerts.common.AlertingResult.StatusCode.OK;
/**
* An object that validates and compiles correlation alerting rules
*
* <p>This objects provides functionality for validating and compiling correlation alerting rules.
* Moreover, it computes and provides json schema for correlation rules.
*
*
* @author Marian Novotny
* @see AlertingCompiler
*
*/
public class AlertingCorrelationRulesCompiler implements AlertingCompiler {
private static final ObjectReader JSON_RULES_READER =
@@ -38,6 +49,9 @@ public class AlertingCorrelationRulesCompiler implements AlertingCompiler {
this.jsonSchemaValidator = jsonSchemaValidator;
}
/**
* {@inheritDoc}
*/
@Override
public AlertingResult compile(String rules, TestingLogger logger) {
AlertingResult validateSchemaResult = validateRulesSyntax(rules);
@@ -121,26 +135,48 @@ public class AlertingCorrelationRulesCompiler implements AlertingCompiler {
}
}
/**
* {@inheritDoc}
*/
@Override
public JsonSchemaValidator getSchemaValidator() {
return jsonSchemaValidator;
}
/**
* This method is not implemented yet
*
* @throws UnsupportedOperationException
*/
@Override
public AlertingResult testRule(String rule, String event) {
throw new UnsupportedOperationException(NOT_IMPLEMENTED_YET_MSG);
}
/**
* This method is not implemented yet
*
* @throws UnsupportedOperationException
*/
@Override
public AlertingResult testRules(String rules, String event) {
throw new UnsupportedOperationException(NOT_IMPLEMENTED_YET_MSG);
}
/**
* Factory method for creating AlertingCorrelationRulesCompiler instance
*
* @return AlertingCorrelationRulesCompiler instance
* @throws Exception if creation of the instance fails
*/
public static AlertingCompiler createAlertingCorrelationRulesCompiler() throws Exception {
JsonSchemaValidator validator = new SiembolJsonSchemaValidator(CorrelationRulesDto.class);
return new AlertingCorrelationRulesCompiler(validator);
}
/**
* {@inheritDoc}
*/
@Override
public String wrapRuleToRules(String ruleStr) throws IOException {
CorrelationRuleDto rule = JSON_RULE_READER.readValue(ruleStr);
@@ -149,5 +185,4 @@ public class AlertingCorrelationRulesCompiler implements AlertingCompiler {
rules.setRules(Arrays.asList(rule));
return JSON_RULES_WRITER.writeValueAsString(rules);
}
}

View File

@@ -17,7 +17,17 @@ import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import static uk.co.gresearch.siembol.alerts.common.AlertingResult.StatusCode.OK;
/**
* An object that validates, test and compiles standard alerting rules
*
* <p>This object provides functionality for validating, testing and compiling alerting rules.
* Moreover, it computes and provides json schema for alerting rules.
*
*
* @author Marian Novotny
* @see AlertingCompiler
*
*/
public class AlertingRulesCompiler implements AlertingCompiler {
private static final ObjectReader JSON_RULES_READER =
new ObjectMapper().readerFor(RulesDto.class);
@@ -100,6 +110,9 @@ public class AlertingRulesCompiler implements AlertingCompiler {
}
}
/**
* {@inheritDoc}
*/
@Override
public AlertingResult compile(String rules, TestingLogger logger) {
AlertingResult validateSchemaResult = validateRulesSyntax(rules);
@@ -171,11 +184,17 @@ public class AlertingRulesCompiler implements AlertingCompiler {
}
}
/**
* {@inheritDoc}
*/
@Override
public JsonSchemaValidator getSchemaValidator() {
return jsonSchemaValidator;
}
/**
* {@inheritDoc}
*/
@Override
public AlertingResult testRules(String rules, String event) {
TestingLogger logger = new StringTestingLogger();
@@ -212,6 +231,9 @@ public class AlertingRulesCompiler implements AlertingCompiler {
return testResult;
}
/**
* {@inheritDoc}
*/
@Override
public String wrapRuleToRules(String ruleStr) throws IOException {
RuleDto rule = JSON_RULE_READER.readValue(ruleStr);
@@ -222,6 +244,12 @@ public class AlertingRulesCompiler implements AlertingCompiler {
return JSON_RULES_WRITER.writeValueAsString(rules);
}
/**
* Factory method for creating AlertingRulesCompiler instance
*
* @return AlertingRulesCompiler instance
* @throws Exception if creation of the instance fails
*/
public static AlertingCompiler createAlertingRulesCompiler() throws Exception {
JsonSchemaValidator validator = new SiembolJsonSchemaValidator(RulesDto.class);
return new AlertingRulesCompiler(validator);

View File

@@ -1,5 +1,16 @@
package uk.co.gresearch.siembol.alerts.compiler;
/**
* An enum of matcher types
*
* @author Marian Novotny
* @see #REGEX_MATCH
* @see #IS_IN_SET
* @see #CONTAINS
* @see #COMPOSITE_OR
* @see #COMPOSITE_AND
* @see #NUMERIC_COMPARE
*
*/
public enum MatcherType {
REGEX_MATCH("REGEX_MATCH"),
IS_IN_SET("IS_IN_SET"),

View File

@@ -1,10 +1,19 @@
package uk.co.gresearch.siembol.alerts.correlationengine;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* An object that represents an alert context stored in alerting counters
*
* <p>This object stores the context of the alert used by alerting counters.
* It stores timestamp and field values that will be included after triggering the rule.
* It implements Comparable interface by comparing timestamps.
*
* @author Marian Novotny
* @see AlertCounter
*
*/
public class AlertContext implements Comparable<AlertContext> {
private final long timestamp;
private final Object[] fieldsToSend;

View File

@@ -3,7 +3,18 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
/**
* An object that implements alerting counters using heap data structure
*
* <p>This object implements alerting counters using PriorityQueue of alerting contexts.
* It evaluates a new alert and supports cleaning of old alerting contexts.
*
*
* @author Marian Novotny
* @see AlertContext
* @see AlertCounterMetadata
*
*/
public class AlertCounter {
private final AlertCounterMetadata counterMetadata;
private final PriorityQueue<AlertContext> alertContextHeap = new PriorityQueue<>();

View File

@@ -1,7 +1,16 @@
package uk.co.gresearch.siembol.alerts.correlationengine;
import java.util.EnumSet;
/**
* An object that represents constant alert counter information
*
* <p>This object stores the constant alert counter metadata.
* It is shared between all counters of the same type in order to save the space.
*
* @author Marian Novotny
* @see AlertCounter
*
*/
public class AlertCounterMetadata {
public enum Flags {
MANDATORY

View File

@@ -10,7 +10,15 @@ import java.util.Map;
import java.util.HashMap;
import static uk.co.gresearch.siembol.alerts.common.AlertingTags.CORRELATION_KEY_TAG_NAME;
/**
* An object that evaluates alerts using correlation rules
*
* <p>This class implements AlertingEngine interface for evaluating alerts using correlation rules.
*
* @author Marian Novotny
* @see AlertingEngine
*
*/
public class CorrelationEngineImpl implements AlertingEngine {
private static final String MISSING_CORRELATION_ATTRIBUTES = "Missing fields for alert correlation";
private final Map<String, List<CorrelationRule>> alertToCorrelationRulesMap;
@@ -18,6 +26,11 @@ public class CorrelationEngineImpl implements AlertingEngine {
private final TimeProvider timeProvider;
private final List<Pair<String, Object>> outputFields;
/**
* Creates correlation engine using builder pattern.
*
* @param builder correlation engine builder
*/
CorrelationEngineImpl(Builder builder) {
alertToCorrelationRulesMap = builder.alertToCorrelationRulesMap;
correlationRules = builder.correlationRules;
@@ -25,6 +38,17 @@ public class CorrelationEngineImpl implements AlertingEngine {
this.outputFields = builder.outputFields;
}
/**
* Evaluate alert using correlation rules and returns alerting result with
* a matching result and additional attributes such as matching events or exceptions.
* It returns matches of all rules.
* The rule is correlated based on correlation key field in the alert and
* alerting rule name field is used for counting alerts in the rules.
*
* @param alert deserialized event as map of string to object
* @return alerting result after evaluation
* @see AlertingResult
*/
@Override
public AlertingResult evaluate(Map<String, Object> alert) {
if (!(alert.get(AlertingFields.RULE_NAME.getAlertingName()) instanceof String)
@@ -68,11 +92,17 @@ public class CorrelationEngineImpl implements AlertingEngine {
return new AlertingResult(AlertingResult.StatusCode.OK, attributes);
}
/**
* {@inheritDoc}
*/
@Override
public AlertingEngineType getAlertingEngineType() {
return AlertingEngineType.SIEMBOL_CORRELATION_ALERTS;
}
/**
* {@inheritDoc}
*/
@Override
public void clean() {
long currentTime = timeProvider.getCurrentTimeInMs();
@@ -81,6 +111,14 @@ public class CorrelationEngineImpl implements AlertingEngine {
}
}
/**
* A builder for correlation alerting engine
*
* <p>This class is using Builder pattern.
*
*
* @author Marian Novotny
*/
public static class Builder {
private static final String MISSING_ARGUMENTS = "Missing required correlation alerting engine properties";
private Map<String, List<CorrelationRule>> alertToCorrelationRulesMap = new HashMap<>();
@@ -91,26 +129,57 @@ public class CorrelationEngineImpl implements AlertingEngine {
private List<Pair<String, Object>> protections;
private List<Pair<String, Object>> outputFields = new ArrayList<>();
/**
* Sets time provider for providing the current time
*
* @param timeProvider time provider
* @return this builder
*/
public Builder timeProvider(TimeProvider timeProvider) {
this.timeProvider = timeProvider;
return this;
}
/**
* Sets correlation rules that should be prepared in advance
*
* @param rules list of correlation alerting rules
* @return this builder
*/
public Builder correlationRules(List<CorrelationRule> rules) {
this.correlationRules = rules;
return this;
}
/**
* Sets key-value pairs that will be put into the event after matching a rule
*
* @param constants list of key-value pairs
* @return this builder
*/
public Builder constants(List<Pair<String, String>> constants) {
this.constants = constants;
return this;
}
/**
* Sets key-value pairs with rule protection information
* that will be put into the event after matching a rule
*
* @param protections list of key-value pairs
* @return this builder
*/
public Builder protections(List<Pair<String, Object>> protections) {
this.protections = protections;
return this;
}
/**
* Builds the correlation alerting engine
*
* @return correlation engine built from the builder state
* @throws IllegalArgumentException in case of wrong arguments
*/
public AlertingEngine build() {
if (correlationRules == null
|| correlationRules.isEmpty()

View File

@@ -11,7 +11,15 @@ import java.util.*;
import java.util.stream.Collectors;
import static uk.co.gresearch.siembol.alerts.common.AlertingTags.CORRELATION_KEY_TAG_NAME;
/**
* An object for representing correlation alerting rule
*
* <p>This derived class of AbstractRule is implementing a correlation alerting rule
*
*
* @author Marian Novotny
* @see AbstractRule
*/
public class CorrelationRule extends AbstractRule {
public enum Flags {
USE_EVENT_TIME,
@@ -28,6 +36,11 @@ public class CorrelationRule extends AbstractRule {
private final List<String> fieldNamesToSend;
/**
* Creates correlation rule using builder pattern.
*
* @param builder CorrelationRule builder
*/
protected CorrelationRule(Builder<?> builder) {
super(builder);
this.alertsThresholds = builder.alertsThresholds;
@@ -38,6 +51,21 @@ public class CorrelationRule extends AbstractRule {
this.alertToCounterIndex = builder.alertToCounterIndex;
this.fieldNamesToSend = builder.fieldNamesToSend;
}
/**
* Evaluates the rule by correlating the alert with other alerts based on the correlation key.
* It uses alert counters to count alerts with thresholds specified in the alert counter metadata.
* It includes the matching result with attributes in alerting result.
* It includes correlated alerts into the attributes after triggering the rule.
*
*
* @param alert map of string to object
* @return alerting result after evaluation
* @see AlertingResult
* @see AlertCounter
* @see AlertCounterMetadata
*
*/
@Override
public AlertingResult match(Map<String, Object> alert) {
String alertName = (String)alert.get(AlertingFields.RULE_NAME.getAlertingName());
@@ -70,6 +98,11 @@ public class CorrelationRule extends AbstractRule {
}
}
/**
* Removes unused old internal state in rule counters
*
* @param currentTime current time in milliseconds
*/
public void clean(long currentTime) {
long waterMark = currentTime - timeWindowInMs - maxLagTimeInMs;
alertCounters.keySet().removeIf(x -> cleanAlertCounters(alertCounters.get(x), waterMark));
@@ -147,6 +180,14 @@ public class CorrelationRule extends AbstractRule {
return ret;
}
/**
* A builder for a correlation alerting rule
*
* <p>This abstract class is derived from AbstractRule.Builder class
*
*
* @author Marian Novotny
*/
public static abstract class Builder<T extends CorrelationRule> extends AbstractRule.Builder<T>{
protected static final String ALERT_ALREADY_EXISTS_MSG = "Duplicate alert names for correlation";
protected static final String INVALID_ALERT_COUNTER = "Invalid alert counter specification";
@@ -165,27 +206,61 @@ public class CorrelationRule extends AbstractRule {
protected Map<String, Integer> alertToCounterIndex = new HashMap<>();
protected EnumSet<Flags> flags = EnumSet.noneOf(Flags.class);
protected List<String> fieldNamesToSend = new ArrayList<>();
/**
* Sets the number of alerts that needs to match
*
* @param alertThresholds threshold for number of alerts to match
* @return this builder
*/
public Builder<T> alertsThresholds(Integer alertThresholds) {
this.alertsThresholds = alertThresholds;
return this;
}
/**
* Sets the time sliding window in milliseconds
*
* @param timeWindowInMs sliding window for evaluation in milliseconds
* @return this builder
*/
public Builder<T> timeWindowInMs(long timeWindowInMs) {
this.timeWindowInMs = timeWindowInMs;
return this;
}
/**
* Sets the maximum lag of alerts in milliseconds.
* The alerts older than this time can be cleaned and will be not considered during evaluation.
*
* @param maxLagTimeInSec maximum lag of alerts
* @return this builder
*/
public Builder<T> maxLagTimeInSec(Integer maxLagTimeInSec) {
this.maxLagTimeInSec = maxLagTimeInSec;
return this;
}
/**
* Sets correlation rule flags
*
* @param flags correlation rule flags
* @return this builder
* @see Flags
*/
public Builder<T> flags(EnumSet<Flags> flags) {
this.flags = flags;
return this;
}
/**
* Adds alert counter into the rule
*
* @param alertName the name of the alert for correlation
* @param threshold threshold of alerts for the counter
* @param flags alert counter metadata flags
* @return this builder
* @see AlertCounterMetadata.Flags
*/
public Builder<T> addAlertCounter(String alertName, int threshold, EnumSet<AlertCounterMetadata.Flags> flags) {
if (threshold <= 0 || threshold > MAX_ALERT_THRESHOLD || alertName == null) {
throw new IllegalArgumentException(INVALID_ALERT_COUNTER);
@@ -196,12 +271,23 @@ public class CorrelationRule extends AbstractRule {
return this;
}
/**
* Sets alert field names that will be included in the correlated alerts' field after triggering the rule
*
* @param fieldNames the list of field names
* @return this builder
*/
public Builder<T> fieldNamesToSend(List<String> fieldNames) {
this.fieldNamesToSend = fieldNames;
return this;
}
}
/**
* Creates CorrelationRule builder instance
*
* @return CorrelationRule builder
*/
public static CorrelationRule.Builder<CorrelationRule> builder() {
return new CorrelationRule.Builder<>() {

View File

@@ -11,7 +11,16 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* An object for alerting rule
*
* <p>This abstract class is using template pattern for handling common functionality of all alerting rules.
*
*
* @author Marian Novotny
* @see Rule
* @see uk.co.gresearch.siembol.alerts.correlationengine.CorrelationRule
*/
public abstract class AbstractRule {
private final String ruleName;
private final String fullRuleName;
@@ -20,6 +29,11 @@ public abstract class AbstractRule {
private final List<Pair<String, String>> variableOutputFields;
protected final TestingLogger logger;
/**
* Creates rule using builder pattern
*
* @param builder abstract rule builder
*/
protected AbstractRule(Builder<?> builder) {
this.ruleName = builder.ruleName;
this.fullRuleName = builder.fullRuleName;
@@ -28,14 +42,29 @@ public abstract class AbstractRule {
this.logger = builder.logger;
}
/**
* Provides rule name
*
* @return the name of the rule
*/
public String getRuleName() {
return ruleName;
}
/**
* Provides full rule name including the rule version
*
* @return the name of the rule including the version
*/
public String getFullRuleName() {
return fullRuleName;
}
/**
* Puts metadata about the rule into the event
*
* @param event the metadata will be put in the event map
*/
public void addOutputFieldsToEvent(Map<String, Object> event) {
outputFields.forEach(x -> event.put(x.getKey(), x.getValue()));
for (Pair<String, String> variableOutputField : variableOutputFields) {
@@ -44,8 +73,25 @@ public abstract class AbstractRule {
}
}
public abstract AlertingResult match(Map<String, Object> log);
/**
* Abstract method to be implemented in derived classes.
* Evaluates the rule and includes the matching result with attributes in alerting result.
*
* @param event map of string to object
* @return alerting result after evaluation
* @see AlertingResult
*
*/
public abstract AlertingResult match(Map<String, Object> event);
/**
* An abstract builder for alerting rules
*
* <p>This abstract class is using Builder pattern.
*
*
* @author Marian Novotny
*/
public static abstract class Builder<T extends AbstractRule> {
private static final String MISSING_ARGUMENTS = "Missing required rule properties";
private String ruleName;
@@ -59,6 +105,12 @@ public abstract class AbstractRule {
protected abstract T buildInternally();
/**
* Builds the alerting rule
*
* @return alerting rule built from the builder state and by calling buildInternally method
* @throws IllegalArgumentException in case of wrong arguments
*/
public T build() {
if (ruleName == null
|| ruleVersion == null) {
@@ -80,30 +132,60 @@ public abstract class AbstractRule {
return buildInternally();
}
/**
* Sets name of the rule in builder
*
* @param name name of the rule
* @return this builder
*/
public Builder<T> name(String name) {
this.ruleName = name;
return this;
}
/**
* Sets version of the rule in builder
*
* @param version version of the rule
* @return this builder
*/
public Builder<T> version(Integer version) {
this.ruleVersion = version;
return this;
}
/**
* Sets the tags - list of key value pairs
*
* @param tags list of key value pairs. Values can include variables for substitution.
* @return this builder
*/
public Builder<T> tags(List<Pair<String, String>> tags) {
this.tags = tags;
return this;
}
/**
* Sets the protections - list of key value pairs with maximum allowed matches
*
* @param protections list of key value pairs for rule protection
* @return this builder
*/
public Builder<T> protections(List<Pair<String, Object>> protections) {
this.protections = protections;
return this;
}
/**
* Sets the testing logger
*
* @param logger testing logger with debugging information about matching
* @return this builder
* @see TestingLogger
*/
public Builder<T> logger(TestingLogger logger) {
this.logger = logger;
return this;
}
}
}

View File

@@ -7,13 +7,26 @@ import uk.co.gresearch.siembol.alerts.common.*;
import uk.co.gresearch.siembol.common.constants.SiembolMessageFields;
import java.util.*;
/**
* An object that evaluates events using alerting rules
*
* <p>This class implements AlertingEngine interface for evaluating events using standard alerting rules.
*
* @author Marian Novotny
* @see AlertingEngine
*
*/
public class AlertingEngineImpl implements AlertingEngine {
private final String sourceField;
private final Map<String, List<Rule>> sourceToRulesTable;
private final List<Rule> allSourceRules;
private final List<Pair<String, Object>> outputFields;
/**
* Creates Alerting engine using builder pattern.
*
* @param builder alerting engine builder
*/
private AlertingEngineImpl(Builder builder) {
this.sourceToRulesTable = builder.sourceToRulesTable;
this.outputFields = builder.outputFields;
@@ -21,6 +34,15 @@ public class AlertingEngineImpl implements AlertingEngine {
this.allSourceRules = builder.allSourceRules;
}
/**
* Evaluates event using alerting rules and returns alerting result with
* a matching result and additional attributes such as matching events or exceptions.
* It returns matches of all rules.
*
* @param event deserialized event as map of string to object
* @return alerting result after evaluation
* @see AlertingResult
*/
@Override
public AlertingResult evaluate(Map<String, Object> event) {
if (!(event.get(sourceField) instanceof String)) {
@@ -54,6 +76,9 @@ public class AlertingEngineImpl implements AlertingEngine {
return new AlertingResult(AlertingResult.StatusCode.OK, attributes);
}
/**
* {@inheritDoc}
*/
@Override
public AlertingEngineType getAlertingEngineType() {
return AlertingEngineType.SIEMBOL_ALERTS;
@@ -88,6 +113,14 @@ public class AlertingEngineImpl implements AlertingEngine {
}
}
/**
* A builder for alerting engine
*
* <p>This class is using Builder pattern.
*
*
* @author Marian Novotny
*/
public static class Builder {
private static final String MISSING_ARGUMENTS = "Missing required alerting engine properties";
private String sourceField = SiembolMessageFields.SENSOR_TYPE.toString();
@@ -99,31 +132,68 @@ public class AlertingEngineImpl implements AlertingEngine {
private List<Pair<String, Object>> protections;
private List<Pair<String, Object>> outputFields = new ArrayList<>();
/**
* Sets source fields in builder with default value: `source_type`
*
* @param sourceField name of the field for source type
* @return this builder
*/
public Builder sourceField(String sourceField) {
this.sourceField = sourceField;
return this;
}
/**
* Sets wildcard in builder with default value: `*`
*
* @param wildcardSource string that will match all source types
* @return this builder
*/
public Builder wildcardSource(String wildcardSource) {
this.wildcardSource = wildcardSource;
return this;
}
/**
* Sets alerting rules that should be prepared in advance
*
* @param rules list of pairs of source type and alerting rule
* @return this builder
*/
public Builder rules(List<Pair<String, Rule>> rules) {
this.rules = rules;
return this;
}
/**
* Sets key-value pairs that will be putted into event after matching a rule
*
* @param constants list of key-value pairs
* @return this builder
*/
public Builder constants(List<Pair<String, String>> constants) {
this.constants = constants;
return this;
}
/**
* Sets key-value pairs with rule protection information
* that will be putted into event after matching a rule
*
* @param protections list of key-value pairs
* @return this builder
*/
public Builder protections(List<Pair<String, Object>> protections) {
this.protections = protections;
return this;
}
/**
* Builds the alerting engine
*
* @return alerting engine built from the builder state
* @throws IllegalArgumentException in case of wrong arguments
*/
public AlertingEngine build() {
if (rules == null
|| rules.isEmpty()

View File

@@ -3,11 +3,30 @@ package uk.co.gresearch.siembol.alerts.engine;
import uk.co.gresearch.siembol.alerts.common.EvaluationResult;
import java.util.Map;
/**
* An object for basic matching an event
*
* <p>This abstract class is using template pattern for handling common functionality of all basic matchers.
* The matcher is created for a field.
*
*
* @author Marian Novotny
* @see Matcher
* @see IsInSetMatcher
* @see ContainsMatcher
* @see RegexMatcher
* @see NumericCompareMatcher
*/
public abstract class BasicMatcher implements Matcher {
private final static String MISSING_FIELD_NAME = "Missing field name in a basic matcher";
private final String fieldName;
private final boolean isNegated;
/**
* Creates basic matcher using builder pattern.
*
* @param builder Basic matcher builder
*/
protected BasicMatcher(Builder<?> builder) {
if (builder.fieldName == null) {
throw new IllegalArgumentException(MISSING_FIELD_NAME);
@@ -17,13 +36,21 @@ public abstract class BasicMatcher implements Matcher {
this.isNegated = builder.isNegated;
}
public EvaluationResult match(Map<String, Object> log) {
if (log.get(fieldName) == null) {
/**
* Extracts fieldValue from the event and calls matchInternally abstract method.
* It negates the result if the matcher is negated.
*
* @param map map of string to object
* @return the evaluation result after evaluation
* @see EvaluationResult
*/
public EvaluationResult match(Map<String, Object> map) {
if (map.get(fieldName) == null) {
return isNegated ? EvaluationResult.MATCH : EvaluationResult.NO_MATCH;
}
var fieldValue = log.get(fieldName);
EvaluationResult result = matchInternally(log, fieldValue);
var fieldValue = map.get(fieldName);
EvaluationResult result = matchInternally(map, fieldValue);
if (isNegated) {
result = EvaluationResult.negate(result);
@@ -32,26 +59,63 @@ public abstract class BasicMatcher implements Matcher {
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean canModifyEvent() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isNegated() {
return isNegated;
}
/**
* Abstract method to be implemented in derived classes. Evaluates fieldValue internally using event if necessary.
* It returns matching statues without considering negated property.
*
*
* @param map event as map of string to object
* @param fieldValue value of the field for matching
* @return matching result after evaluation
*
*/
protected abstract EvaluationResult matchInternally(Map<String, Object> map, Object fieldValue);
/**
* An abstract builder for basic matchers
*
* <p>This abstract class is using Builder pattern.
*
*
* @author Marian Novotny
*/
public static abstract class Builder<T extends BasicMatcher> {
private String fieldName;
private boolean isNegated = false;
/**
* Sets fieldName in builder
*
* @param name field in which matcher will be registered
* @return this builder
*/
public Builder<T> fieldName(String name) {
this.fieldName = name;
return this;
}
/**
* Sets negated in builder
*
* @param isNegated matcher is negated
* @return this builder
*/
public Builder<T> isNegated(boolean isNegated) {
this.isNegated = isNegated;
return this;

View File

@@ -7,33 +7,66 @@ import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
* An object for matching an event by evaluation of compositions of matchers
*
* <p>This class is for composing basic and composite matchers.
* The matcher is not created for a field and can contain basic matchers registered on different fields.
*
*
* @author Marian Novotny
* @see Matcher
*/
public class CompositeMatcher implements Matcher {
private final Function<Map<String, Object>, EvaluationResult> evaluationFunction;
private final boolean negated;
private final boolean canModifyEvent;
/**
* Creates composite matcher using builder pattern.
*
* @param builder composite matcher builder
*/
public CompositeMatcher(Builder builder) {
this.evaluationFunction = builder.evaluationFunction;
this.negated = builder.negated;
this.canModifyEvent = builder.canModifyEvent;
}
/**
* Match the event and returns evaluation result.
* The event is evaluated by underlying matchers and combined by logical functions such as AND, OR.
*
* @param event map of string to object
* @return the evaluation result after evaluation
* @see EvaluationResult
*/
@Override
public EvaluationResult match(Map<String, Object> log) {
EvaluationResult matchersResult = evaluationFunction.apply(log);
public EvaluationResult match(Map<String, Object> event) {
EvaluationResult matchersResult = evaluationFunction.apply(event);
return negated ? EvaluationResult.negate(matchersResult) : matchersResult;
}
/**
* {@inheritDoc}
*/
@Override
public boolean canModifyEvent() {
return canModifyEvent;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isNegated() {
return negated;
}
/**
* Creates Composite matcher builder instance.
*
* @return Contains matcher builder
*/
public static Builder builder() {
return new Builder();
}
@@ -57,7 +90,14 @@ public class CompositeMatcher implements Matcher {
return EvaluationResult.MATCH;
}
/**
* A builder for composite matchers
*
* <p>This class is using Builder pattern.
*
*
* @author Marian Novotny
*/
public static class Builder {
private static final String EMPTY_MATCHERS = "Empty matchers in the composite matcher";
private static final String WRONG_ARGUMENTS = "wrong arguments in the composite matcher";
@@ -72,21 +112,46 @@ public class CompositeMatcher implements Matcher {
private Function<Map<String, Object>, EvaluationResult> evaluationFunction;
private boolean canModifyEvent;
/**
* Sets the matcher type for evaluating the composition
*
* @param matcherType COMPOSITE_OR or COMPOSITE_AND
* @return this builder
* @see MatcherType
*/
public Builder matcherType(MatcherType matcherType) {
this.matcherType = matcherType;
return this;
}
/**
* Sets the matcher is negated
*
* @param negated the matcher is negated
* @return this builder
*/
public Builder isNegated(boolean negated) {
this.negated = negated;
return this;
}
/**
* Sets the list of underlying matchers that should be created in advance
*
* @param matchers the list of underlying matchers
* @return this builder
*/
public Builder matchers(List<Matcher> matchers) {
this.matchers = matchers;
return this;
}
/**
* Builds the composite matcher
*
* @return composite matcher built from the builder state
* @throws IllegalArgumentException in case of wrong arguments
*/
public CompositeMatcher build() {
if (matchers == null || matchers.isEmpty()) {
throw new IllegalArgumentException(EMPTY_MATCHERS);

View File

@@ -5,7 +5,17 @@ import uk.co.gresearch.siembol.common.utils.EvaluationLibrary;
import java.util.*;
import java.util.function.BiPredicate;
/**
* An object for basic matching of substring for an event
*
* <p>This derived class of BasicMatcher provides functionality for matching a substring.
* It supports case-insensitive string comparisons and
* substituting variables using current map and string search after the substitution and
* specifying matching at start or end of the string.
*
* @author Marian Novotny
* @see BasicMatcher
*/
public class ContainsMatcher extends BasicMatcher {
enum Flags {
CONTAINS_VARIABLE,
@@ -19,6 +29,11 @@ public class ContainsMatcher extends BasicMatcher {
protected final String pattern;
protected final BiPredicate<String, String> checkPredicate;
/**
* Creates contains matcher using builder pattern.
*
* @param builder ContainsMatcher builder
*/
private ContainsMatcher(ContainsMatcher.Builder<?> builder) {
super(builder);
this.flags = builder.flags;
@@ -26,6 +41,15 @@ public class ContainsMatcher extends BasicMatcher {
this.checkPredicate = builder.checkPredicate;
}
/**
* Evaluates fieldValue internally using substring search. It substitutes the variables if needed.
* it supports case-insensitive compare if specified and checks for starting or ending requirements if needed.
*
* @param map event as map of string to object
* @param fieldValue value of the field for matching
* @return EvaluationResult.MATCH if field value contains the string otherwise EvaluationResult.NO_MATCH
*
*/
@Override
protected EvaluationResult matchInternally(Map<String, Object> map, Object fieldValue) {
var fieldStringValue = fieldValue.toString();
@@ -49,6 +73,11 @@ public class ContainsMatcher extends BasicMatcher {
: EvaluationResult.NO_MATCH;
}
/**
* Creates Contains matcher builder instance.
*
* @return Contains matcher builder
*/
public static Builder<ContainsMatcher> builder() {
return new Builder<>() {
@@ -72,12 +101,26 @@ public class ContainsMatcher extends BasicMatcher {
};
}
/**
* A builder for Contains matchers
*
* <p>This abstract class is derived from BasicMatcher.Builder class.
*
*
* @author Marian Novotny
*/
public static abstract class Builder<T extends ContainsMatcher>
extends BasicMatcher.Builder<T> {
protected EnumSet<Flags> flags = EnumSet.noneOf(Flags.class);
protected String pattern;
protected BiPredicate<String, String> checkPredicate;
/**
* Sets startsWith flag in builder
*
* @param startsWith matcher is checking whether the substring starts with the string
* @return this builder
*/
public ContainsMatcher.Builder<T> isStartsWith(boolean startsWith) {
if (startsWith) {
flags.add(Flags.STARTS_WITH);
@@ -85,6 +128,12 @@ public class ContainsMatcher extends BasicMatcher {
return this;
}
/**
* Sets endsWith flag in builder
*
* @param endsWith matcher is checking whether the substring ends with the string
* @return this builder
*/
public ContainsMatcher.Builder<T> isEndsWith(boolean endsWith) {
if (endsWith) {
flags.add(Flags.ENDS_WITH);
@@ -92,6 +141,12 @@ public class ContainsMatcher extends BasicMatcher {
return this;
}
/**
* Sets case-insensitive comparing in builder
*
* @param caseInsensitiveCompare matcher is comparing strings case-insensitively
* @return this builder
*/
public ContainsMatcher.Builder<T> isCaseInsensitiveCompare(boolean caseInsensitiveCompare) {
if (caseInsensitiveCompare) {
flags.add(Flags.CASE_INSENSITIVE);
@@ -99,6 +154,12 @@ public class ContainsMatcher extends BasicMatcher {
return this;
}
/**
* Sets input string to search
*
* @param data string to search
* @return this builder
*/
public ContainsMatcher.Builder<T> data(String data) {
if (data == null) {
throw new IllegalArgumentException(EMPTY_PATTERN_MSG);

View File

@@ -5,13 +5,27 @@ import uk.co.gresearch.siembol.alerts.common.EvaluationResult;
import java.util.*;
import java.util.stream.Collectors;
/**
* An object for basic matching of a set of strings for an event
*
* <p>This derived class of BasicMatcher provides functionality for matching set of strings.
* It supports case-insensitive string comparisons and
* substituting variables using current map and matching the field after the substitution.
*
* @author Marian Novotny
* @see BasicMatcher
*/
public class IsInSetMatcher extends BasicMatcher {
private final static String EMPTY_SET_OF_STRING = "Empty constantStrings of string in the matcher";
private final Set<String> constantStrings;
private final List<String> variableStrings;
private final boolean caseInsensitiveCompare;
/**
* Creates is in set matcher using builder pattern.
*
* @param builder IsInSetMatcher builder
*/
private IsInSetMatcher(Builder<?> builder) {
super(builder);
this.constantStrings = builder.constantStrings;
@@ -19,6 +33,15 @@ public class IsInSetMatcher extends BasicMatcher {
this.caseInsensitiveCompare = builder.caseInsensitiveCompare;
}
/**
* Evaluates fieldValue internally using set of strings. It substitutes the variables if needed.
* it supports case-insensitive compare if specified.
*
* @param map event as map of string to object
* @param fieldValue value of the field for matching
* @return EvaluationResult.MATCH if one string matches otherwise EvaluationResult.NO_MATCH
*
*/
@Override
protected EvaluationResult matchInternally(Map<String, Object> map, Object fieldValue) {
var fieldStringValue = fieldValue.toString();
@@ -44,6 +67,11 @@ public class IsInSetMatcher extends BasicMatcher {
: EvaluationResult.NO_MATCH;
}
/**
* Creates IsInSet matcher builder instance.
*
* @return IsInSet matcher builder
*/
public static Builder<IsInSetMatcher> builder() {
return new Builder<>() {
@@ -67,6 +95,14 @@ public class IsInSetMatcher extends BasicMatcher {
};
}
/**
* A builder for IsInSet matchers
*
* <p>This abstract class is derived from BasicMatcher.Builder class.
*
*
* @author Marian Novotny
*/
public static abstract class Builder<T extends IsInSetMatcher>
extends BasicMatcher.Builder<T> {
private String wordDelimiter = "\n";
@@ -75,21 +111,45 @@ public class IsInSetMatcher extends BasicMatcher {
protected Set<String> constantStrings;
protected List<String> variableStrings;
/**
* Sets wordDelimiter in builder
*
* @param wordDelimiter is used for splitting words from data string
* @return this builder
*/
public IsInSetMatcher.Builder<T> wordDelimiter(String wordDelimiter) {
this.wordDelimiter = wordDelimiter;
return this;
}
/**
* Sets case-insensitive comparing in builder
*
* @param caseInsensitiveCompare matcher is comparing strings case-insensitively
* @return this builder
*/
public IsInSetMatcher.Builder<T> isCaseInsensitiveCompare(boolean caseInsensitiveCompare) {
this.caseInsensitiveCompare = caseInsensitiveCompare;
return this;
}
/**
* Sets words as one string in builder
*
* @param data set of words in one string delimited using word delimiter
* @return this builder
*/
public IsInSetMatcher.Builder<T> data(String data) {
String[] words = data.split(wordDelimiter);
return words(Arrays.asList(words));
}
/**
* Sets words as list of strings in builder
*
* @param words list of words for
* @return this builder
*/
public IsInSetMatcher.Builder<T> words(List<String> words) {
this.words = words;
return this;

View File

@@ -4,8 +4,39 @@ import uk.co.gresearch.siembol.alerts.common.EvaluationResult;
import java.util.Map;
/**
* An object for matching an event
*
* <p>This interface for matching an event and providing metadata for a caller such us
* the matcher is negated, or whether it can modify the event.
*
*
* @author Marian Novotny
* @see uk.co.gresearch.siembol.alerts.engine.AlertingEngineImpl
* @see Rule
* @see BasicMatcher
* @see CompositeMatcher
*/
public interface Matcher {
EvaluationResult match(Map<String, Object> log);
/**
* Matches the event and returns evaluation result.
*
* @param event map of string to object
* @return the evaluation result after evaluation
* @see EvaluationResult
*/
EvaluationResult match(Map<String, Object> event);
/**
* Provides information whether the matcher can modify the event and
* the caller needs to consider it before matching.
*
* @return true if the matcher can modify the event, otherwise false
*/
boolean canModifyEvent();
/**
* Provides information whether the matcher is negated
*
* @return true if the matcher is negated, otherwise false
*/
boolean isNegated();
}

View File

@@ -7,18 +7,43 @@ import java.util.*;
import java.util.function.BiPredicate;
import java.util.function.Function;
/**
* An object for numeric comparing a field with an expression - a constant or other field in an event
*
* <p>This derived class of BasicMatcher provides functionality for numeric comparing.
* It supports custom comparator and
* substituting variables using current map and comparing after the substitution.
*
* @author Marian Novotny
* @see BasicMatcher
*/
public class NumericCompareMatcher extends BasicMatcher {
private static final String MISSING_ARGUMENTS_MSG = "Missing attributes in NumericMatcher";
private static final String WRONG_CONSTANT_FORMAT = "Can not convert %s into a number";
private final BiPredicate<Double, Double> comparator;
private final Function<Map<String, Object>, Optional<Double>> valueSupplier;
/**
* Creates numeric comparison matcher using builder pattern.
*
* @param builder NumericCompare matcher builder
*/
private NumericCompareMatcher(NumericCompareMatcher.Builder<?> builder) {
super(builder);
this.comparator = builder.comparator;
this.valueSupplier = builder.valueSupplier;
}
/**
* Interprets fieldValue as a number and compares it with an expression.
* It substitutes the variable in expression if needed.
*
* @param map event as map of string to object
* @param fieldValue value of the field for matching
* @return EvaluationResult.MATCH if comparing numeric field with expression returns true,
* otherwise EvaluationResult.NO_MATCH
*
*/
@Override
protected EvaluationResult matchInternally(Map<String, Object> map, Object fieldValue) {
var doubleFieldValue = getDoubleFromObject(fieldValue);
@@ -63,6 +88,11 @@ public class NumericCompareMatcher extends BasicMatcher {
return getDoubleFromObject(substituted.get());
}
/**
* Creates NumericCompare matcher builder instance.
*
* @return NumericCompare matcher builder
*/
public static NumericCompareMatcher.Builder<NumericCompareMatcher> builder() {
return new NumericCompareMatcher.Builder<>() {
@Override
@@ -87,16 +117,36 @@ public class NumericCompareMatcher extends BasicMatcher {
};
}
/**
* A builder for NumericCompare matchers
*
* <p>This abstract class is derived from BasicMatcher.Builder class.
*
*
* @author Marian Novotny
*/
public static abstract class Builder<T extends NumericCompareMatcher> extends BasicMatcher.Builder<T> {
protected BiPredicate<Double, Double> comparator;
protected Function<Map<String, Object>, Optional<Double>> valueSupplier;
protected String expression;
/**
* Sets a numeric comparator in builder
*
* @param comparator numeric comparator bi-predicate that will be used during matching
* @return this builder
*/
public NumericCompareMatcher.Builder<T> comparator(BiPredicate<Double, Double> comparator) {
this.comparator = comparator;
return this;
}
/**
* Sets a numeric expression in builder
*
* @param expression string numeric constant or a variable
* @return this builder
*/
public NumericCompareMatcher.Builder<T> expression(String expression) {
this.expression = expression;
return this;

View File

@@ -4,7 +4,15 @@ import uk.co.gresearch.siembol.alerts.common.EvaluationResult;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* An object for basic regular matching of an event
*
* <p>This derived class of BasicMatcher provides functionality for regular expression matching.
* It supports extracting fields and put them into an event using regular expression named groups.
*
* @author Marian Novotny
* @see BasicMatcher
*/
public class RegexMatcher extends BasicMatcher {
private static final String EMPTY_PATTERN = "Empty pattern";
private static final Pattern VARIABLE_PATTERN =
@@ -15,17 +23,36 @@ public class RegexMatcher extends BasicMatcher {
private final Pattern pattern;
private final List<String> variableNames;
/**
* Creates regex matcher using builder pattern.
*
* @param builder Regex matcher builder
*/
private RegexMatcher(Builder<?> builder) {
super(builder);
this.pattern = builder.pattern;
this.variableNames = builder.variableNames;
}
/**
* Provides information whether the matcher can modify the event and
* the caller needs to consider it before matching.
*
* @return true if the regex matcher contains variables - named group matching
*/
@Override
public boolean canModifyEvent() {
return !variableNames.isEmpty();
}
/**
* Evaluates fieldValue internally using pattern. It puts extracted fields if the pattern contains named groups.
*
* @param map event as map of string to object
* @param fieldValue value of the field for matching
* @return EvaluationResult.MATCH if pattern matches otherwise EvaluationResult.NO_MATCH
*
*/
@Override
protected EvaluationResult matchInternally(Map<String, Object> map, Object fieldValue) {
var fieldStringValue = fieldValue.toString();
@@ -42,6 +69,11 @@ public class RegexMatcher extends BasicMatcher {
return EvaluationResult.MATCH;
}
/**
* Creates regex matcher builder instance.
*
* @return regex matcher builder
*/
public static RegexMatcher.Builder<RegexMatcher> builder() {
return new RegexMatcher.Builder<>() {
@@ -55,11 +87,26 @@ public class RegexMatcher extends BasicMatcher {
};
}
/**
* A builder for regular expression matchers
*
* <p>This abstract class is derived from BasicMatcher.Builder class
*
*
* @author Marian Novotny
*/
public static abstract class Builder<T extends RegexMatcher>
extends BasicMatcher.Builder<T> {
protected Pattern pattern;
protected List<String> variableNames;
/**
* Compiles pattern from string in builder. Renames named groups since regular expression supports
* characters: `_`, `:`, which are forbidden in Java patterns
*
* @param patternStr regular expression specification
* @return this builder
*/
public RegexMatcher.Builder<T> pattern(String patternStr) {
//NOTE: java regex does not support : _ in variable names but we want it
variableNames = new ArrayList<>();

View File

@@ -3,7 +3,15 @@ package uk.co.gresearch.siembol.alerts.engine;
import uk.co.gresearch.siembol.alerts.common.EvaluationResult;
import uk.co.gresearch.siembol.alerts.common.AlertingResult;
import java.util.*;
/**
* An object for alerting rule
*
* <p>This derived class of AbstractRule is implementing a standard alerting rule
*
*
* @author Marian Novotny
* @see AbstractRule
*/
public class Rule extends AbstractRule {
public enum RuleFlags {
CAN_MODIFY_EVENT,
@@ -13,15 +21,30 @@ public class Rule extends AbstractRule {
private final List<Matcher> matchers;
private final EnumSet<RuleFlags> flags;
/**
* Creates rule using builder pattern.
*
* @param builder Rule builder
*/
protected Rule(Builder<?> builder) {
super(builder);
this.matchers = builder.matchers;
this.flags = builder.flags;
}
/**
* Evaluates the rule by calling underlying matchers - all matchers are required to match to return MATCH result.
* It includes the matching result with attributes in alerting result.
* It creates a copy of the event if the rule can modify the event during the evaluation.
*
* @param event map of string to object
* @return alerting result after evaluation
* @see AlertingResult
*
*/
@Override
public AlertingResult match(Map<String, Object> log) {
Map<String, Object> current = canModifyEvent() ? new HashMap<>(log) : log;
public AlertingResult match(Map<String, Object> event) {
Map<String, Object> current = canModifyEvent() ? new HashMap<>(event) : event;
for (Matcher matcher : matchers) {
EvaluationResult result = matcher.match(current);
if (result == EvaluationResult.NO_MATCH) {
@@ -37,22 +60,48 @@ public class Rule extends AbstractRule {
return AlertingResult.fromEvaluationResult(EvaluationResult.MATCH, current);
}
/**
* Provides information whether the rule can modify the event during evaluation.
* It is used by match method
*
* @return true if the rule can modify the event otherwise false
*/
public boolean canModifyEvent() {
return flags.contains(RuleFlags.CAN_MODIFY_EVENT);
}
/**
* A builder for an alerting rule
*
* <p>This abstract class is derived from AbstractRule.Builder class
*
*
* @author Marian Novotny
*/
public static abstract class Builder<T extends Rule> extends AbstractRule.Builder<T>{
protected static final String MISSING_MATCHERS = "Empty matchers in a rule";
protected static final String NEGATED_MATCHERS_ONLY = "The rule contains negated matchers only";
protected List<Matcher> matchers;
protected EnumSet<RuleFlags> flags = EnumSet.noneOf(RuleFlags.class);
/**
* Sets the list of matchers
*
* @param matchers list of matchers
* @return this builder
*/
public Builder<T> matchers(List<Matcher> matchers) {
this.matchers = matchers;
return this;
}
/**
* Sets the flags of the rule
*
* @param flags flags of the rule
* @return this builder
* @see RuleFlags
*/
public Builder<T> flags(EnumSet<RuleFlags> flags) {
this.flags = EnumSet.copyOf(flags);
return this;
@@ -76,6 +125,11 @@ public class Rule extends AbstractRule {
}
}
/**
* Creates Rule builder instance
*
* @return Rule builder
*/
public static Builder<Rule> builder() {
return new Builder<>() {

View File

@@ -2,7 +2,17 @@ package uk.co.gresearch.siembol.alerts.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
/**
* A data transfer object for representing correlation alerts used in correlation attributes
*
* <p>This class is used for json (de)serialisation of a correlation alert and
* for generating json schema from this class using annotations.
*
* @author Marian Novotny
* @see com.github.reinert.jjschema.Attributes
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see CorrelationAttributesDto
*/
@Attributes(title = "correlation alert", description = "Correlation alert specification")
public class CorrelationAlertDto {
@JsonProperty("alert")

View File

@@ -4,7 +4,17 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
import java.util.List;
/**
* A data transfer object for representing alerting correlation attributes
*
* <p>This class is used for json (de)serialisation of an alerting correlation attributes and
* for generating json schema from this class using annotations.
*
* @author Marian Novotny
* @see com.github.reinert.jjschema.Attributes
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see CorrelationRuleDto
*/
@Attributes(title = "correlation attributes", description = "Correlation attributes of real-time correlation alert matching")
public class CorrelationAttributesDto {
@JsonProperty("time_unit")

View File

@@ -4,7 +4,17 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
import java.util.List;
/**
* A data transfer object for representing alerting correlation rule
*
* <p>This class is used for json (de)serialisation of an alerting correlation rule and
* for generating json schema from this class using annotations.
*
* @author Marian Novotny
* @see com.github.reinert.jjschema.Attributes
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see CorrelationRulesDto
*/
@Attributes(title = "correlation rule", description = "Correlation rule for real-time correlation alert matching")
public class CorrelationRuleDto {
@JsonProperty("rule_name")

View File

@@ -6,7 +6,16 @@ import uk.co.gresearch.siembol.alerts.common.AlertingTags;
import java.util.Arrays;
import java.util.List;
/**
* A data transfer object for representing alerting correlation rules
*
* <p>This class is used for json (de)serialisation of alerting correlation rules and
* for generating json schema from this class using annotations.
*
* @author Marian Novotny
* @see com.github.reinert.jjschema.Attributes
* @see com.fasterxml.jackson.annotation.JsonProperty
*/
@Attributes(title = "correlation rules", description = "Correlation rules for real-time correlation alert matching")
public class CorrelationRulesDto {
public CorrelationRulesDto() {

View File

@@ -4,7 +4,17 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
import java.util.List;
/**
* A data transfer object for representing an alerting matcher used in alerting rules
*
* <p>This class is used for json (de)serialisation of an alerting matcher and
* for generating json schema from this class using annotations.
*
* @author Marian Novotny
* @see com.github.reinert.jjschema.Attributes
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see RuleDto
*/
@Attributes(title = "matcher", description = "Matcher for matching fields")
public class MatcherDto {
@Attributes(description = "The matcher is enabled", required = false)

View File

@@ -2,7 +2,21 @@ package uk.co.gresearch.siembol.alerts.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
/**
* An enum for representing a matcher type used in alerting rules
*
* <p>This enum is used for json (de)serialisation of matcher type.
*
* @author Marian Novotny
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see MatcherDto
* @see #REGEX_MATCH
* @see #IS_IN_SET
* @see #CONTAINS
* @see #COMPOSITE_AND
* @see #COMPOSITE_OR
* @see #NUMERIC_COMPARE
*/
@Attributes(title = "time computation type", description = "Type of time computation")
public enum MatcherTypeDto {
@JsonProperty("REGEX_MATCH") REGEX_MATCH("REGEX_MATCH"),

View File

@@ -2,9 +2,19 @@ package uk.co.gresearch.siembol.alerts.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
import uk.co.gresearch.siembol.alerts.common.AlertingResult;
import java.util.function.BiPredicate;
/**
* An enum for representing a comparing type used in numeric matcher
*
* <p>This enum is used for json (de)serialisation of comparing type and providing a comparator for the type.
*
* @author Marian Novotny
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see MatcherDto
*
*/
@Attributes(title = "numeric compare type", description = "Type of numeric comparison")
public enum NumericCompareTypeDto {
@JsonProperty("equal")
@@ -30,6 +40,11 @@ public enum NumericCompareTypeDto {
return name;
}
/**
* Provides the comparator predicate for the numeric compare type.
*
* @return the comparator for the compare type
*/
public BiPredicate<Double, Double> getComparator() {
return comparator;
}

View File

@@ -3,7 +3,17 @@ package uk.co.gresearch.siembol.alerts.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
import java.util.List;
/**
* A data transfer object for representing alerting rule
*
* <p>This class is used for json (de)serialisation of an alerting rule and
* for generating json schema from this class using annotations.
*
* @author Marian Novotny
* @see com.github.reinert.jjschema.Attributes
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see RulesDto
*/
@Attributes(title = "rule", description = "Rule for real-time alert matching")
public class RuleDto {
@JsonProperty("rule_name")

View File

@@ -2,7 +2,18 @@ package uk.co.gresearch.siembol.alerts.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
/**
* A data transfer object for representing a rule protection specification used in alerting rules
*
* <p>This class is used for json (de)serialisation of a rule protection specification and
* for generating json schema from this class using annotations.
*
* @author Marian Novotny
* @see com.github.reinert.jjschema.Attributes
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see RuleDto
* @see CorrelationRuleDto
*/
@Attributes(title = "rule protection", description = "Thresholds for deactivating the rule")
public class RuleProtectionDto {
@JsonProperty("max_per_hour")

View File

@@ -6,7 +6,16 @@ import uk.co.gresearch.siembol.alerts.common.AlertingTags;
import java.util.Arrays;
import java.util.List;
/**
* A data transfer object for representing alerting rules
*
* <p>This class is used for json (de)serialisation of alerting rules and
* for generating json schema from this class using annotations.
*
* @author Marian Novotny
* @see com.github.reinert.jjschema.Attributes
* @see com.fasterxml.jackson.annotation.JsonProperty
*/
@Attributes(title = "rules", description = "Rules for real-time alert matching")
public class RulesDto {
public RulesDto() {

View File

@@ -2,7 +2,18 @@ package uk.co.gresearch.siembol.alerts.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
/**
* A data transfer object for representing a tag used in alerting rules
*
* <p>This class is used for json (de)serialisation of a tag and
* for generating json schema from this class using annotations.
*
* @author Marian Novotny
* @see com.github.reinert.jjschema.Attributes
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see RuleDto
* @see CorrelationRuleDto
*/
@Attributes(title = "tag", description = "The tag pair added to the event after matching")
public class TagDto {
@JsonProperty("tag_name")

View File

@@ -2,7 +2,17 @@ package uk.co.gresearch.siembol.alerts.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
/**
* An enum for representing a time computation type used in correlation attributes
*
* <p>This enum is used for json (de)serialisation of time computation type.
*
* @author Marian Novotny
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see CorrelationAttributesDto
* @see #EVENT_TIME
* @see #PROCESSING_TIME
*/
@Attributes(title = "time computation type", description = "Type of time computation")
public enum TimeComputationTypeDto {
@JsonProperty("event_time") EVENT_TIME("event_time"),

View File

@@ -2,7 +2,18 @@ package uk.co.gresearch.siembol.alerts.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
/**
* An enum for representing a time unit type used in correlation attributes
*
* <p>This enum is used for json (de)serialisation of time unit type.
*
* @author Marian Novotny
* @see com.fasterxml.jackson.annotation.JsonProperty
* @see CorrelationAttributesDto
* @see #MINUTES
* @see #HOURS
* @see #SECONDS
*/
@Attributes(title = "time unit type", description = "Time unit type for sliding window alert counting")
public enum TimeUnitTypeDto {
@JsonProperty("minutes") MINUTES("minutes", 60 * 1000L),

View File

@@ -2,7 +2,32 @@ package uk.co.gresearch.siembol.alerts.protection;
import uk.co.gresearch.siembol.alerts.common.AlertingResult;
/**
* An object for counting rule matches
*
* <p>This interface is used for counting rule matches and
* providing hourly and daily matches of a rule.
*
* @author Marian Novotny
* @see RuleProtectionSystemImpl
*
*/
public interface RuleProtectionSystem {
/**
* Increments rule matches and returns hourly and daily matches
*
* @param fullRuleName full rule name
* @return alerting result with hourly and daily matches of the rule after incrementing
* @see AlertingResult
*/
AlertingResult incrementRuleMatches(String fullRuleName);
/**
* Returns hourly and daily matches
*
* @param fullRuleName full rule name
* @return alerting result with hourly and daily matches of the rule
* @see AlertingResult
*/
AlertingResult getRuleMatches(String fullRuleName);
}

View File

@@ -5,12 +5,24 @@ import uk.co.gresearch.siembol.alerts.common.AlertingResult;
import java.util.Map;
import java.util.HashMap;
/**
* An object for counting rule matches using simple in memory counter
*
* <p>This class implements RuleProtectionSystem interface using simple in-memory counting.
*
*
* @author Marian Novotny
* @see RuleProtectionSystem
* @see SimpleCounter
*
*/
public class RuleProtectionSystemImpl implements RuleProtectionSystem {
private static final String UNKNOWN_RULE = "No matches of the rule %s";
private final Map<String, SimpleCounter> ruleCounters = new HashMap<>();
/**
* {@inheritDoc}
*/
@Override
public AlertingResult incrementRuleMatches(String fullRuleName) {
if (!ruleCounters.containsKey(fullRuleName)) {
@@ -26,6 +38,9 @@ public class RuleProtectionSystemImpl implements RuleProtectionSystem {
return new AlertingResult(AlertingResult.StatusCode.OK, attr);
}
/**
* {@inheritDoc}
*/
@Override
public AlertingResult getRuleMatches(String fullRuleName) {
if (!ruleCounters.containsKey(fullRuleName)) {

View File

@@ -1,7 +1,15 @@
package uk.co.gresearch.siembol.alerts.protection;
import uk.co.gresearch.siembol.common.utils.TimeProvider;
/**
* An object that counts hourly and daily matches
*
* <p>This object counts hourly and daily matches using simple counting and
* current time provided by TimeProvider.
*
* @author Marian Novotny
*
*/
public class SimpleCounter {
private final TimeProvider timeProvider;
private int lastDay = -1;

View File

@@ -5,7 +5,14 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import uk.co.gresearch.siembol.common.model.testing.AlertingSparkArgumentDto;
import java.util.Base64;
/**
* A main class of alerting spark application
*
* <p>This class provides the main function that is executed during submission of a spark job.
*
* @author Marian Novotny
*
*/
public class AlertingSpark {
private static final String APP_NAME = "SiembolAlertingSpark";
private static final String MISSING_ATTRIBUTES = "Missing testing attributes";

View File

@@ -2,12 +2,24 @@ package uk.co.gresearch.siembol.spark;
import uk.co.gresearch.siembol.alerts.common.AlertingEngine;
import uk.co.gresearch.siembol.alerts.compiler.AlertingRulesCompiler;
import uk.co.gresearch.siembol.common.zookeeper.ZooKeeperConnector;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* An object for integration of an alerting engine into a spark application
*
* <p>This class implements Serializable interface.
* It serializes engine using alerting rules json string.
* It provides functionality for evaluating an event using the alerting engine.
*
* @author Marian Novotny
* @see AlertingEngine
* @see AlertingSparkResult
*
*/
public class AlertingSparkEngine implements Serializable {
private static final long serialVersionUID = 1L;
private static final String ALERTING_RULE_COMPILATION_ERROR = "Exception during compiling alerting rules";

View File

@@ -6,7 +6,21 @@ import org.apache.spark.api.java.JavaSparkContext;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
/**
* An object for a spark job that evaluates events using an alerting spark engine
*
* <p>This class implements Serializable interface.
* It uses initialised AlertingSparkEngine instance to evaluate
* resilient distributed dataset (RDD) of json strings of events using the MapReduce technique.
* AlertingSparkEngine, RDD of events and a Spark context are provided by the builder in the constructor.
*
* @author Marian Novotny
* @see AlertingSparkEngine
* @see JavaRDD
* @see Builder
* @see AlertingSparkResult
*
*/
public class AlertingSparkJob implements Serializable {
private static final long serialVersionUID = 1L;
private final JavaRDD<String> rdd;
@@ -27,6 +41,19 @@ public class AlertingSparkJob implements Serializable {
.fold(AlertingSparkResult.emptyResult(maxResult), AlertingSparkResult::merge);
}
/**
* An object for construction AlertingSparkJob instance
*
* <p>This class uses Builder pattern.
* It initialises AlertingSparkEngine from rules, RDD of events from files paths and a Spark context.
*
* @author Marian Novotny
* @see AlertingSparkEngine
* @see JavaRDD
* @see AlertingSparkJob
* @see JavaSparkContext
*
*/
public static class Builder {
private static final String MISSING_ARGUMENTS_MSG = "Missing arguments for alerts spark job";
private static final String EMPTY_FILES_PATHS_MSG = "Files paths are empty";

View File

@@ -11,7 +11,17 @@ import uk.co.gresearch.siembol.common.model.testing.AlertingSparkTestingResultDt
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Map;
/**
* An object for representing alerting spark result
*
* <p>This class implements Serializable interface. It contains a list of matched events (json strings) and
* the list of exceptions (json strings of ErrorMessages).
* It provides functionality for merging two alerting results that is used in the map reduce job.
*
* @author Marian Novotny
* @see AlertingSparkTestingResultDto
*
*/
public class AlertingSparkResult implements Serializable {
private static final long serialVersionUID = 1L;

View File

@@ -34,7 +34,18 @@ import uk.co.gresearch.siembol.common.model.AlertingStormAttributesDto;
import java.lang.invoke.MethodHandles;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
/**
* An object for integration of an alerting engine into a storm bolt
*
* <p>This class extends a Storm BaseRichBolt class to implement a Storm bolt, that
* evaluates events using an engine initialised from the rules cached in the ZooKeeper,
* watches for the rules update in ZooKeeper and updates the rules without need to restart the topology or the bolt,
* emits alerts and exceptions after matching.
* @author Marian Novotny
* @see AlertingEngine
* @see ZooKeeperConnector
*
*/
public class AlertingEngineBolt extends BaseRichBolt {
private static final long serialVersionUID = 1L;
private static final String EXCEPTION_MSG_FORMAT = "Alerting Engine exception: %s during evaluating event: %s";

View File

@@ -18,7 +18,21 @@ import uk.co.gresearch.siembol.common.model.AlertingStormAttributesDto;
import uk.co.gresearch.siembol.common.storm.KafkaWriterAnchor;
import uk.co.gresearch.siembol.common.storm.KafkaWriterBoltBase;
import uk.co.gresearch.siembol.common.storm.KafkaWriterMessage;
import uk.co.gresearch.siembol.common.zookeeper.ZooKeeperConnector;
/**
* An object for evaluating alerting protection matches and writing alerts to a kafka topic
*
* <p>This class extends a Storm BaseRichBolt class in order to implement a Storm bolt, that
* evaluates events using an engine initialised from the rules cached in the ZooKeeper,
* watches for the rules update in ZooKeeper and updates the rules without need to restart the topology or the bolt and
* emits alerts and exceptions after matching.
*
* @author Marian Novotny
* @see KafkaWriterBoltBase
* @see ZooKeeperConnector
*
*/
public class AlertingKafkaWriterBolt extends KafkaWriterBoltBase {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

View File

@@ -26,7 +26,17 @@ import java.util.Base64;
import static org.apache.kafka.clients.consumer.ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG;
import static org.apache.kafka.clients.consumer.ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG;
/**
* A main class of alerting storm topology
*
* <p>This class provides helper function to build an alerting topology and
* provides main function that is executed during submission of a storm topology.
*
* @author Marian Novotny
* @see AlertingEngineBolt
* @see AlertingKafkaWriterBolt
*
*/
public class AlertingStorm {
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final String KAFKA_SPOUT = "kafka-spout";

View File

@@ -10,13 +10,27 @@ import uk.co.gresearch.siembol.alerts.common.AlertingEngine;
import uk.co.gresearch.siembol.alerts.common.AlertingResult;
import uk.co.gresearch.siembol.alerts.compiler.AlertingCorrelationRulesCompiler;
import uk.co.gresearch.siembol.common.model.AlertingStormAttributesDto;
import uk.co.gresearch.siembol.common.zookeeper.ZooKeeperConnector;
import java.lang.invoke.MethodHandles;
import java.util.List;
import java.util.Map;
import static org.apache.storm.utils.TupleUtils.isTick;
import static org.apache.storm.utils.TupleUtils.putTickFrequencyIntoComponentConfig;
/**
* An object for integration of a correlation alerting engine into a storm bolt
*
* <p>This class extends a Storm AlertingBolt class to implement a Storm bolt, that
* evaluates events using an correlation engine initialised form the rules cached in the ZooKeeper,
* watches for the rules update in ZooKeeper and updates the rules without need to restart the topology or the bolt,
* emits alerts and exceptions after matching.
* It cleans regularly internal state of counters by calling clean method of the alerting engine.
*
* @author Marian Novotny
* @see AlertingEngine
* @see ZooKeeperConnector
*
*/
public class CorrelationAlertingEngineBolt extends AlertingEngineBolt {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

View File

@@ -1,5 +1,16 @@
package uk.co.gresearch.siembol.alerts.storm;
/**
* An enum of tuple field names used in alerting storm topology
*
* @author Marian Novotny
*
* @see #EVENT
* @see #ALERTING_MATCHES
* @see #CORRELATION_KEY
* @see #ALERTING_EXCEPTIONS
* @see #CORRELATION_KEY
*
*/
public enum TupleFieldNames {
EVENT("event"),
ALERTING_MATCHES("matches"),

View File

@@ -8,7 +8,15 @@ import java.io.Serializable;
import java.util.EnumSet;
import java.util.Map;
import java.util.Optional;
/**
* A serializable object for representing an alerting message after triggering by an alerting engine
*
* <p>This class implements serializable interface and is used for representing an alerting message after
* being triggered by an alerting engine.
*
* @author Marian Novotny
*
*/
public class AlertMessage implements Serializable {
private static final long serialVersionUID = 1L;
private static final String MISSING_FIELDS_MSG = "Missing siembol alerting fields in alert: %s";

View File

@@ -1,7 +1,16 @@
package uk.co.gresearch.siembol.alerts.storm.model;
import java.util.ArrayList;
/**
* A serializable object for representing list of alerting messages after triggering by an alerting engine
*
* <p>This class implements serializable interface and is used for representing list of alerting messages after
* being triggered by an alerting engine.
*
* @author Marian Novotny
* @see AlertMessage
*
*/
public class AlertMessages extends ArrayList<AlertMessage> {
private static final long serialVersionUID = 1L;
}

View File

@@ -1,7 +1,16 @@
package uk.co.gresearch.siembol.alerts.storm.model;
import java.util.ArrayList;
/**
* A serializable object for representing list of exceptions
*
* <p>This class implements serializable interface and is used for representing list of exception messages
* as json string of an ErrorMessage.
*
* @author Marian Novotny
* @see uk.co.gresearch.siembol.common.error.ErrorMessage
*
*/
public class ExceptionMessages extends ArrayList<String> {
private static final long serialVersionUID = 1L;
}