Skip to content

Commit

Permalink
stage rule-engine
Browse files Browse the repository at this point in the history
Signed-off-by: Chase Engelbrecht <[email protected]>
  • Loading branch information
engechas committed May 2, 2024
1 parent 730d563 commit eb13db4
Show file tree
Hide file tree
Showing 31 changed files with 2,558 additions and 7 deletions.
7 changes: 7 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM opensearchproject/opensearch:2.11.1
RUN if [ -d /usr/share/opensearch/plugins/opensearch-alerting ]; then /usr/share/opensearch/bin/opensearch-plugin remove opensearch-alerting; fi
RUN if [ -d /usr/share/opensearch/plugins/opensearch-security-analytics ]; then /usr/share/opensearch/bin/opensearch-plugin remove opensearch-security-analytics; fi
ADD build/distributions/opensearch-alerting-2.11.1.0-SNAPSHOT.zip /tmp/
ADD build/distributions/opensearch-security-analytics-2.11.1.0-SNAPSHOT.zip /tmp/
RUN /usr/share/opensearch/bin/opensearch-plugin install --batch file:/tmp/opensearch-alerting-2.11.1.0-SNAPSHOT.zip
RUN /usr/share/opensearch/bin/opensearch-plugin install --batch file:/tmp/opensearch-security-analytics-2.11.1.0-SNAPSHOT.zip
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ dependencies {
implementation group: 'org.apache.commons', name: 'commons-lang3', version: "${versions.commonslang}"
implementation "org.antlr:antlr4-runtime:4.10.1"
implementation "com.cronutils:cron-utils:9.1.6"
api "org.opensearch:common-utils:${common_utils_version}@jar"
api(files('/Users/engechas/security-analytics/common-utils/build/libs/common-utils-3.0.0.0-SNAPSHOT.jar'))
api "org.opensearch.client:opensearch-rest-client:${opensearch_version}"
implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
compileOnly "org.opensearch:opensearch-job-scheduler-spi:${opensearch_build}"
Expand Down
17 changes: 17 additions & 0 deletions rule-engine/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'jacoco'

repositories {
Expand All @@ -15,4 +16,20 @@ repositories {
dependencies {
implementation rootProject
implementation "com.github.seancfoley:ipaddress:5.4.1"
implementation "org.apache.commons:commons-lang3:3.14.0"
implementation "commons-io:commons-io:2.16.1"

implementation platform("org.apache.logging.log4j:log4j-bom:2.22.1")
implementation "org.apache.logging.log4j:log4j-core"
implementation "org.yaml:snakeyaml:2.1"

testImplementation "org.mockito:mockito-inline:5.2.0"
testImplementation "org.mockito:mockito-core:5.11.0"
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.1'
}

test {
useJUnitPlatform()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
package org.opensearch.securityanalytics.ruleengine.cloudtrail;

import org.opensearch.securityanalytics.ruleengine.model.DataType;

public class CloudTrail extends DataType {
// TODO - versioning on log types
private String eventName;
private long time;

public CloudTrail() {
super();
}

@Override
public Object getValue(final String fieldName) {
switch (fieldName) {
case "eventName": return eventName;
case "time": return time;
default: throw new UnsupportedOperationException("Unknown field name: " + fieldName);
}
}

@Override
public String getTimeFieldName() {
return "time";
}

public void setEventName(final String eventName) {
this.eventName = eventName;
}

public void setTime(final long time) {
this.time = time;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,51 @@

import org.opensearch.securityanalytics.ruleengine.model.DataType;
import org.opensearch.securityanalytics.ruleengine.model.Match;
import org.opensearch.securityanalytics.ruleengine.rules.StatelessRule;
import org.opensearch.securityanalytics.ruleengine.store.RuleStore;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class StatelessRuleEvaluator implements RuleEvaluator<DataType> {
private final RuleStore ruleStore;

public StatelessRuleEvaluator(final RuleStore ruleStore) {
this.ruleStore = ruleStore;
}

@Override
public List<Match> evaluate(final List<DataType> data) {
return null;
if (data.isEmpty()) {
return Collections.emptyList();
}

final List<StatelessRule> rules = ruleStore.getStatelessRules();
if (rules.isEmpty()) {
return Collections.emptyList();
}

return data.stream()
.map(datum -> evaluateRules(datum, rules))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

private Match evaluateRules(final DataType datum, final List<StatelessRule> rules) {
final List<StatelessRule> ruleMatches = rules.stream()
.filter(rule -> rule.getEvaluationCondition().test(datum))
.filter(rule -> rule.getRuleCondition().test(datum))
.collect(Collectors.toList());

if (ruleMatches.isEmpty()) {
return null;
}

final Match match = new Match(datum);
match.addStatelessRules(ruleMatches);

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

public class RuleEvaluationException extends RuntimeException {
public RuleEvaluationException(final String message) {
super(message);
}
public RuleEvaluationException(final String message, final Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
package org.opensearch.securityanalytics.ruleengine.exception;

public class RuleParseException extends RuntimeException {
public RuleParseException(final String message) {
super(message);
}

public RuleParseException(final String message, final Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
package org.opensearch.securityanalytics.ruleengine.field;

import org.opensearch.securityanalytics.ruleengine.exception.RuleEvaluationException;
import org.opensearch.securityanalytics.ruleengine.model.DataType;

import java.util.Collections;
import java.util.Map;

public class FieldAccessor {
private final Map<String, String> fieldTranslations;

public FieldAccessor(final Map<String, String> fieldTranslations) {
this.fieldTranslations = fieldTranslations == null ? Collections.emptyMap() : fieldTranslations;
}

public String getStringValue(final DataType dataType, final String fieldName) {
return getValue(dataType, convertFieldName(fieldName), String.class);
}

public Boolean getBooleanValue(final DataType dataType, final String fieldName) {
return getValue(dataType, convertFieldName(fieldName), Boolean.class);
}

public Integer getIntegerValue(final DataType dataType, final String fieldName) {
return getValue(dataType, convertFieldName(fieldName), Integer.class);
}

public Float getFloatValue(final DataType dataType, final String fieldName) {
return getValue(dataType, convertFieldName(fieldName), Float.class);
}

public Double getDoubleValue(final DataType dataType, final String fieldName) {
return getValue(dataType, convertFieldName(fieldName), Double.class);
}

public Object getObjectValue(final DataType dataType, final String fieldName) {
return getValue(dataType, convertFieldName(fieldName), Object.class);
}

private <T> T getValue(final DataType dataType, final String fieldName, final Class<T> clazz) {
try {
return clazz.cast(dataType.getValue(fieldName));
} catch (final ClassCastException e) {
throw new RuleEvaluationException("Unable to cast field " + fieldName + " to class " + clazz.getName(), e);
}
}

private String convertFieldName(final String fieldName) {
final String mappedFieldName = fieldTranslations.get(fieldName);
return mappedFieldName == null ? fieldName : mappedFieldName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,40 @@
*/
package org.opensearch.securityanalytics.ruleengine.model;

import org.opensearch.securityanalytics.ruleengine.rules.Rule;
import org.opensearch.securityanalytics.ruleengine.rules.StatefulRule;
import org.opensearch.securityanalytics.ruleengine.rules.StatelessRule;

import java.util.ArrayList;
import java.util.List;

public class Match {
private final DataType datum;
private final List<Rule> rules;
private final List<StatelessRule> statelessRules;
private final List<StatefulRule> statefulRules;

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

public void addRule(final Rule rule) {
rules.add(rule);
public void addStatelessRules(final List<StatelessRule> rules) {
statelessRules.addAll(rules);
}

public void addStatefulRules(final List<StatefulRule> rules) {
statefulRules.addAll(rules);
}

public DataType getDatum() {
return datum;
}

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

public List<StatefulRule> getStatefulRules() {
return statefulRules;
}
}
Loading

0 comments on commit eb13db4

Please sign in to comment.