diff --git a/rule-engine/build.gradle b/rule-engine/build.gradle new file mode 100644 index 000000000..40b3df78c --- /dev/null +++ b/rule-engine/build.gradle @@ -0,0 +1,18 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +apply plugin: 'java' +apply plugin: 'jacoco' + +repositories { + mavenLocal() + mavenCentral() + maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } +} + +dependencies { + implementation rootProject + implementation "com.github.seancfoley:ipaddress:5.4.1" +} \ No newline at end of file diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/RuleEngine.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/RuleEngine.java new file mode 100644 index 000000000..f1fb6fe78 --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/RuleEngine.java @@ -0,0 +1,8 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine; + +public class RuleEngine { +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/evaluator/RuleEvaluator.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/evaluator/RuleEvaluator.java new file mode 100644 index 000000000..e126f0ea1 --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/evaluator/RuleEvaluator.java @@ -0,0 +1,19 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.evaluator; + +import org.opensearch.securityanalytics.ruleengine.model.Match; + +import java.util.List; + +public interface RuleEvaluator { + /** + * A method to evaluate the rules against a set of incoming data. + * + * @param data - the data to be evaluated against the rules + * @return - A list of Matches for positive rule evaluations against the incoming data + */ + List evaluate(List data); +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/evaluator/StatelessRuleEvaluator.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/evaluator/StatelessRuleEvaluator.java new file mode 100644 index 000000000..8a3b2d846 --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/evaluator/StatelessRuleEvaluator.java @@ -0,0 +1,17 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.evaluator; + +import org.opensearch.securityanalytics.ruleengine.model.DataType; +import org.opensearch.securityanalytics.ruleengine.model.Match; + +import java.util.List; + +public class StatelessRuleEvaluator implements RuleEvaluator { + @Override + public List evaluate(final List data) { + return null; + } +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/model/DataType.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/model/DataType.java new file mode 100644 index 000000000..f38204230 --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/model/DataType.java @@ -0,0 +1,27 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.model; + +import java.util.HashMap; +import java.util.Map; + +public abstract class DataType { + private final Map dataTypeMetadata; + + public DataType() { + this.dataTypeMetadata = new HashMap<>(); + } + + public abstract Object getValue(String fieldName); + public abstract String getTimeFieldName(); + + public void putDataTypeMetadata(final String key, final String value) { + dataTypeMetadata.put(key, value); + } + + public Map getDataTypeMetadata() { + return dataTypeMetadata; + } +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/model/Match.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/model/Match.java new file mode 100644 index 000000000..ff6eff2c2 --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/model/Match.java @@ -0,0 +1,24 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.model; + +import org.opensearch.securityanalytics.ruleengine.rules.Rule; + +import java.util.ArrayList; +import java.util.List; + +public class Match { + private final DataType datum; + private final List rules; + + public Match(final DataType datum) { + this.datum = datum; + this.rules = new ArrayList<>(); + } + + public void addRule(final Rule rule) { + rules.add(rule); + } +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/parser/RuleParser.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/parser/RuleParser.java new file mode 100644 index 000000000..3cde5a739 --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/parser/RuleParser.java @@ -0,0 +1,18 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.parser; + +import org.opensearch.securityanalytics.ruleengine.provider.RuleData; +import org.opensearch.securityanalytics.ruleengine.rules.ParsedRules; + +public interface RuleParser { + /** + * A method to parse the information of a RuleData object into the internal representation of a rule used for evaluation. + * + * @param ruleData - the information representing one or more rules to be parsed + * @return - A ParsedRules object containing the internal representation of the rules that were parsed + */ + ParsedRules parseRules(RuleData ruleData); +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/provider/RuleData.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/provider/RuleData.java new file mode 100644 index 000000000..4d98add9d --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/provider/RuleData.java @@ -0,0 +1,34 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.provider; + +import org.opensearch.securityanalytics.ruleengine.model.DataType; + +import java.util.Map; +import java.util.function.Predicate; + +public class RuleData { + private final String ruleAsString; + private final Predicate evaluationCondition; + private final Map metadata; + + public RuleData(final String ruleAsString, final Predicate evaluationCondition, final Map metadata) { + this.ruleAsString = ruleAsString; + this.evaluationCondition = evaluationCondition; + this.metadata = metadata; + } + + public String getRuleAsString() { + return ruleAsString; + } + + public Predicate getEvaluationCondition() { + return evaluationCondition; + } + + public Map getMetadata() { + return metadata; + } +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/provider/RuleProvider.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/provider/RuleProvider.java new file mode 100644 index 000000000..fa5f60788 --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/provider/RuleProvider.java @@ -0,0 +1,16 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.provider; + +import java.util.List; + +public interface RuleProvider { + /** + * A method to fetch RuleData from an external source + * + * @return - A list of RuleData used to parse the rules into the internal representation used for evaluation + */ + List getRuleData(); +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/ParsedRules.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/ParsedRules.java new file mode 100644 index 000000000..c71b7862b --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/ParsedRules.java @@ -0,0 +1,25 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.rules; + +import java.util.List; + +public class ParsedRules { + private final List statelessRules; + private final List statefulRules; + + public ParsedRules(final List statelessRules, final List statefulRules) { + this.statelessRules = statelessRules; + this.statefulRules = statefulRules; + } + + public List getStatelessRules() { + return statelessRules; + } + + public List getStatefulRules() { + return statefulRules; + } +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/Rule.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/Rule.java new file mode 100644 index 000000000..6f7cbe5fe --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/Rule.java @@ -0,0 +1,19 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.rules; + +import java.util.function.Predicate; + +public abstract class Rule { + private final String id; + private final Predicate evaluationCondition; + private final Predicate ruleCondition; + + public Rule(final String id, final Predicate evaluationCondition, final Predicate ruleCondition) { + this.id = id; + this.evaluationCondition = evaluationCondition; + this.ruleCondition = ruleCondition; + } +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/StatefulRule.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/StatefulRule.java new file mode 100644 index 000000000..7ae1c6302 --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/StatefulRule.java @@ -0,0 +1,24 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.rules; + +import org.opensearch.securityanalytics.ruleengine.model.Match; + +import java.time.Duration; +import java.util.List; +import java.util.function.Predicate; + +public class StatefulRule extends Rule> { + private final Duration timeframe; + private final List filterFields; + + public StatefulRule(final String id, final Predicate evaluationCondition, + final Predicate> ruleCondition, final Duration timeframe, + final List filterFields) { + super(id, evaluationCondition, ruleCondition); + this.timeframe = timeframe; + this.filterFields = filterFields; + } +} diff --git a/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/StatelessRule.java b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/StatelessRule.java new file mode 100644 index 000000000..492933459 --- /dev/null +++ b/rule-engine/src/main/java/org/opensearch/securityanalytics/ruleengine/rules/StatelessRule.java @@ -0,0 +1,19 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.securityanalytics.ruleengine.rules; + +import org.opensearch.securityanalytics.ruleengine.model.DataType; + +import java.util.function.Predicate; + +public class StatelessRule extends Rule { + private final boolean isStatefulCondition; + + public StatelessRule(final String id, final Predicate evaluationCondition, + final Predicate ruleCondition, final boolean isStatefulCondition) { + super(id, evaluationCondition, ruleCondition); + this.isStatefulCondition = isStatefulCondition; + } +}