Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add interfaces and models for rule engine #990

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions rule-engine/build.gradle
Original file line number Diff line number Diff line change
@@ -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"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a veritable dependency or can we use a dependency already used in core.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed for CIDR range matching which will be introduced in the next PR. Alerting takes a dependency on the same module (but Security Analytics doesn't): https://github.com/opensearch-project/alerting/blob/main/alerting/build.gradle#L116

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
package org.opensearch.securityanalytics.ruleengine;

public class RuleEngine {
}
Original file line number Diff line number Diff line change
@@ -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<T> {
/**
* 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<Match> evaluate(List<T> data);
}
Original file line number Diff line number Diff line change
@@ -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<DataType> {
@Override
public List<Match> evaluate(final List<DataType> data) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -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<String, String> 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<String, String> getDataTypeMetadata() {
return dataTypeMetadata;
}
}
Original file line number Diff line number Diff line change
@@ -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<Rule> rules;

public Match(final DataType datum) {
this.datum = datum;
this.rules = new ArrayList<>();
}

public void addRule(final Rule rule) {
rules.add(rule);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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<DataType> evaluationCondition;
private final Map<String, String> metadata;

public RuleData(final String ruleAsString, final Predicate<DataType> evaluationCondition, final Map<String, String> metadata) {
this.ruleAsString = ruleAsString;
this.evaluationCondition = evaluationCondition;
this.metadata = metadata;
}

public String getRuleAsString() {
return ruleAsString;
}

public Predicate<DataType> getEvaluationCondition() {
return evaluationCondition;
}

public Map<String, String> getMetadata() {
return metadata;
}
}
Original file line number Diff line number Diff line change
@@ -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<RuleData> getRuleData();
}
Original file line number Diff line number Diff line change
@@ -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<StatelessRule> statelessRules;
private final List<StatefulRule> statefulRules;

public ParsedRules(final List<StatelessRule> statelessRules, final List<StatefulRule> statefulRules) {
this.statelessRules = statelessRules;
this.statefulRules = statefulRules;
}

public List<StatelessRule> getStatelessRules() {
return statelessRules;
}

public List<StatefulRule> getStatefulRules() {
return statefulRules;
}
}
Original file line number Diff line number Diff line change
@@ -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<T, U> {
private final String id;
private final Predicate<T> evaluationCondition;
private final Predicate<U> ruleCondition;

public Rule(final String id, final Predicate<T> evaluationCondition, final Predicate<U> ruleCondition) {
this.id = id;
this.evaluationCondition = evaluationCondition;
this.ruleCondition = ruleCondition;
}
}
Original file line number Diff line number Diff line change
@@ -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<Match, List<Match>> {
private final Duration timeframe;
private final List<String> filterFields;

public StatefulRule(final String id, final Predicate<Match> evaluationCondition,
final Predicate<List<Match>> ruleCondition, final Duration timeframe,
final List<String> filterFields) {
super(id, evaluationCondition, ruleCondition);
this.timeframe = timeframe;
this.filterFields = filterFields;
}
}
Original file line number Diff line number Diff line change
@@ -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<DataType, DataType> {
private final boolean isStatefulCondition;

public StatelessRule(final String id, final Predicate<DataType> evaluationCondition,
final Predicate<DataType> ruleCondition, final boolean isStatefulCondition) {
super(id, evaluationCondition, ruleCondition);
this.isStatefulCondition = isStatefulCondition;
}
}
Loading