forked from jtmelton/appsensor
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request jtmelton#79 from dscrobonia/feature-storage-integr…
…ations-2 rule integration with influxdb storage
- Loading branch information
Showing
7 changed files
with
381 additions
and
181 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,8 @@ | |
|
||
import javax.inject.Inject; | ||
|
||
import org.joda.time.DateTime; | ||
import org.joda.time.DateTimeZone; | ||
import org.junit.Before; | ||
import org.junit.BeforeClass; | ||
import org.junit.Test; | ||
|
@@ -23,16 +25,20 @@ | |
import org.owasp.appsensor.core.Threshold; | ||
import org.owasp.appsensor.core.User; | ||
import org.owasp.appsensor.core.analysis.EventAnalysisEngine; | ||
import org.owasp.appsensor.core.configuration.server.ServerConfiguration; | ||
import org.owasp.appsensor.core.criteria.SearchCriteria; | ||
import org.owasp.appsensor.core.rule.Clause; | ||
import org.owasp.appsensor.core.rule.Rule; | ||
import org.owasp.appsensor.core.rule.MonitorPoint; | ||
import org.owasp.appsensor.core.rule.Rule; | ||
import org.springframework.test.context.ContextConfiguration; | ||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||
|
||
/** | ||
* Basic test for the {@link AggregateEventAnalysisEngine}. | ||
* Basic test for the {@link AggregateEventAnalysisEngine}. Built to be extended by other components | ||
* to test integration with the rules engine. | ||
* | ||
* Tests should finish with the last event triggering an attack, so that each test can start | ||
* assuming that only the events created in each test will count towards the attack threshold. | ||
* todo: fix this by clearing events or adding time before each test | ||
* | ||
* @author David Scrobonia ([email protected]) | ||
* @author John Melton ([email protected]) http://www.jtmelton.com/ | ||
|
@@ -42,21 +48,23 @@ | |
@ContextConfiguration(locations={"classpath:base-context.xml"}) | ||
public class SimpleAggregateEventAnalysisEngineTest { | ||
|
||
private static User bob = new User("bob"); | ||
protected static User bob = new User("bob"); | ||
|
||
private static DetectionPoint detectionPoint1 = new DetectionPoint(); | ||
protected static ArrayList<DetectionPoint> detectionPoints = null; | ||
|
||
private static Collection<String> detectionSystems1 = new ArrayList<String>(); | ||
protected static Collection<String> detectionSystems1 = new ArrayList<String>(); | ||
|
||
private static DetectionSystem detectionSystem1 = new DetectionSystem("localhostme"); | ||
protected static DetectionSystem detectionSystem1 = new DetectionSystem("localhostme"); | ||
|
||
private static HashMap<String, SearchCriteria> criteria = new HashMap<String, SearchCriteria>(); | ||
protected static HashMap<String, SearchCriteria> criteria = new HashMap<String, SearchCriteria>(); | ||
|
||
private static AggregateEventAnalysisEngine myEngine = null; | ||
protected static AggregateEventAnalysisEngine rulesEngine = null; | ||
|
||
private static ArrayList<Rule> rules = null; | ||
protected static ArrayList<Rule> rules = null; | ||
|
||
protected int sleepAmount = 10; | ||
protected static DateTime time; | ||
|
||
protected static int SLEEP_AMOUNT = 10; | ||
|
||
@Inject | ||
AppSensorServer appSensorServer; | ||
|
@@ -66,108 +74,107 @@ public class SimpleAggregateEventAnalysisEngineTest { | |
|
||
@BeforeClass | ||
public static void doSetup() { | ||
detectionPoint1.setCategory(DetectionPoint.Category.INPUT_VALIDATION); | ||
detectionPoint1.setLabel("IE1"); | ||
// instantiate member variables | ||
|
||
detectionSystems1.add(detectionSystem1.getDetectionSystemId()); | ||
|
||
detectionPoints = generateDetectionPoints(); | ||
|
||
rules = generateRules(); | ||
|
||
criteria.put("all", new SearchCriteria().setDetectionSystemIds(detectionSystems1)); | ||
|
||
criteria.put("dp1", new SearchCriteria(). | ||
setUser(bob). | ||
setDetectionPoint(detectionPoint1). | ||
setDetectionPoint(new DetectionPoint(DetectionPoint.Category.INPUT_VALIDATION, "IE1")). | ||
setDetectionSystemIds(detectionSystems1)); | ||
|
||
rules = generateRules(); | ||
|
||
criteria.put("rule1", new SearchCriteria(). | ||
setUser(bob). | ||
setRule(rules.get(0)). | ||
setDetectionSystemIds(detectionSystems1)); | ||
|
||
time = DateTime.now().minusMinutes(2).toDateTime(DateTimeZone.UTC); | ||
} | ||
|
||
@Before | ||
public void initializeTest() { | ||
if (myEngine == null) { | ||
initialSetup(); | ||
} | ||
rulesEngine = getRulesEngine(); | ||
|
||
// clear any existing rules & detection points | ||
ArrayList<Rule> emptyRules = new ArrayList<Rule>(); | ||
appSensorServer.getConfiguration().setRules(emptyRules); | ||
|
||
// clear rules | ||
setRule(appSensorServer, null); | ||
ArrayList<DetectionPoint> emptyDps = new ArrayList<DetectionPoint>(); | ||
appSensorServer.getConfiguration().setDetectionPoints(emptyDps); | ||
} | ||
|
||
public void initialSetup() { | ||
//instantiate server | ||
ServerConfiguration updatedConfiguration = appSensorServer.getConfiguration(); | ||
updatedConfiguration.setDetectionPoints(loadMockedDetectionPoints()); | ||
appSensorServer.setConfiguration(updatedConfiguration); | ||
@Test | ||
public void test1_DP1() throws Exception { | ||
// add rules/detection points | ||
ArrayList<Rule> rulesToAdd = new ArrayList<Rule>(); | ||
rulesToAdd.add(rules.get(0)); | ||
appSensorServer.getConfiguration().setRules(rulesToAdd); | ||
|
||
Collection<EventAnalysisEngine> engines = appSensorServer.getEventAnalysisEngines(); | ||
// add detection point | ||
ArrayList<DetectionPoint> dpsToAdd = new ArrayList<DetectionPoint>(); | ||
dpsToAdd.add(detectionPoints.get(0)); | ||
appSensorServer.getConfiguration().setDetectionPoints(dpsToAdd); | ||
|
||
for (EventAnalysisEngine engine : engines) { | ||
if (engine instanceof AggregateEventAnalysisEngine){ | ||
myEngine = (AggregateEventAnalysisEngine)engine; | ||
} | ||
} | ||
DetectionPoint detectionPoint1 = detectionPoints.get(0); | ||
|
||
setRule(appSensorServer, null); | ||
} | ||
// get events and attacks | ||
int numEvents = appSensorServer.getEventStore().findEvents(criteria.get("dp1")).size(); | ||
int numDPAttacks = appSensorServer.getAttackStore().findAttacks(criteria.get("dp1")).size(); | ||
int numRuleAttacks = appSensorServer.getAttackStore().findAttacks(criteria.get("rule1")).size(); | ||
|
||
@Test | ||
public void test1_DP1() throws Exception { | ||
//Add rule | ||
setRule(appSensorServer, rules.get(0)); | ||
// useless sanity check | ||
assertEquals(numEvents, appSensorServer.getEventStore().findEvents(criteria.get("dp1")).size()); | ||
assertEquals(numDPAttacks, appSensorServer.getAttackStore().findAttacks(criteria.get("dp1")).size()); | ||
assertEquals(numRuleAttacks, appSensorServer.getAttackStore().findAttacks(criteria.get("rule1")).size()); | ||
|
||
//is empty | ||
assertEventsAndAttacks(0, 0, criteria.get("all")); | ||
|
||
// 3 events and triggered attack | ||
generateEvents(sleepAmount*3, detectionPoint1, 3, "rule1"); | ||
assertEventsAndAttacks(3, 1, criteria.get("dp1")); | ||
assertEquals(1, appSensorServer.getAttackStore().findAttacks(criteria.get("rule1")).size()); | ||
addEvents(bob, detectionPoint1, 3); | ||
numEvents += 3; numDPAttacks++; numRuleAttacks++; | ||
|
||
assertEquals(numEvents, appSensorServer.getEventStore().findEvents(criteria.get("dp1")).size()); | ||
assertEquals(numDPAttacks, appSensorServer.getAttackStore().findAttacks(criteria.get("dp1")).size()); | ||
assertEquals(numRuleAttacks, appSensorServer.getAttackStore().findAttacks(criteria.get("rule1")).size()); | ||
|
||
// 1 event and no new attack | ||
generateEvents(sleepAmount, detectionPoint1, 1, "rule1"); | ||
assertEventsAndAttacks(4, 1, criteria.get("dp1")); | ||
assertEquals(1, appSensorServer.getAttackStore().findAttacks(criteria.get("rule1")).size()); | ||
addEvent(bob, detectionPoint1); | ||
numEvents += 1; | ||
|
||
assertEquals(numEvents, appSensorServer.getEventStore().findEvents(criteria.get("dp1")).size()); | ||
assertEquals(numDPAttacks, appSensorServer.getAttackStore().findAttacks(criteria.get("dp1")).size()); | ||
assertEquals(numRuleAttacks, appSensorServer.getAttackStore().findAttacks(criteria.get("rule1")).size()); | ||
|
||
// 2 events and 2 total attack | ||
generateEvents(sleepAmount*2, detectionPoint1, 2, "rule1"); | ||
assertEventsAndAttacks(6, 2, criteria.get("dp1")); | ||
assertEquals(2, appSensorServer.getAttackStore().findAttacks(criteria.get("rule1")).size()); | ||
addEvents(bob, detectionPoint1, 2); | ||
numEvents += 2; numDPAttacks++; numRuleAttacks++; | ||
|
||
assertEquals(numEvents, appSensorServer.getEventStore().findEvents(criteria.get("dp1")).size()); | ||
assertEquals(numDPAttacks, appSensorServer.getAttackStore().findAttacks(criteria.get("dp1")).size()); | ||
assertEquals(numRuleAttacks, appSensorServer.getAttackStore().findAttacks(criteria.get("rule1")).size()); | ||
} | ||
|
||
//assumes no rules will be triggered until last event | ||
private void generateEvents (int time, DetectionPoint detectionPoint, int eventCount, String ruleName) throws Exception { | ||
int attackCount = appSensorServer.getAttackStore().findAttacks(criteria.get(ruleName)).size(); | ||
protected void addEvent(User user, DetectionPoint detectionPoint) { | ||
appSensorClient.getEventManager().addEvent(new Event(user, detectionPoint, time.toString(), detectionSystem1)); | ||
time = time.plusMillis(SLEEP_AMOUNT); | ||
|
||
for (int i = 0; i < eventCount; i++) { | ||
assertEquals(attackCount, appSensorServer.getAttackStore().findAttacks(criteria.get(ruleName)).size()); | ||
appSensorClient.getEventManager().addEvent(new Event(bob, detectionPoint, new DetectionSystem("localhostme"))); | ||
Thread.sleep(time/eventCount); | ||
} | ||
} | ||
|
||
private void assertEventsAndAttacks (int eventCount, int attackCount, SearchCriteria criteria) { | ||
if (criteria.getRule() == null) { | ||
assertEquals(eventCount, appSensorServer.getEventStore().findEvents(criteria).size()); | ||
protected void addEvents(User user, DetectionPoint detectionPoint, int count) { | ||
for (int i=0; i<count; i++) { | ||
appSensorClient.getEventManager().addEvent(new Event(user, detectionPoint, time.toString(), detectionSystem1)); | ||
time = time.plusMillis(SLEEP_AMOUNT); | ||
} | ||
assertEquals(attackCount, appSensorServer.getAttackStore().findAttacks(criteria).size()); | ||
} | ||
|
||
private void setRule(AppSensorServer server, Rule rule) { | ||
Collection<Rule> rules = new ArrayList<Rule>(); | ||
rules.add(rule); | ||
ServerConfiguration updatedConfiguration = appSensorServer.getConfiguration(); | ||
updatedConfiguration.setRules(rules); | ||
appSensorServer.setConfiguration(updatedConfiguration); | ||
} | ||
|
||
private static ArrayList<Rule> generateRules() { | ||
final ArrayList<Rule> configuredRules = new ArrayList<Rule>(); | ||
// intervals | ||
Interval minutes5 = new Interval(5, Interval.MINUTES); | ||
Interval minutes16 = new Interval(16, Interval.MINUTES); | ||
|
||
// detection points | ||
MonitorPoint point1 = new MonitorPoint(new DetectionPoint(DetectionPoint.Category.INPUT_VALIDATION, "IE1", new Threshold(3, minutes5))); | ||
|
@@ -182,7 +189,7 @@ private static ArrayList<Rule> generateRules() { | |
// responses | ||
ArrayList<Response> responses = generateResponses(); | ||
|
||
//rule 1: DP1 | ||
// rule 1: DP1 | ||
ArrayList<Clause> clauses1 = new ArrayList<Clause>(); | ||
clauses1.add(clause1); | ||
|
||
|
@@ -191,25 +198,25 @@ private static ArrayList<Rule> generateRules() { | |
ArrayList<org.owasp.appsensor.core.rule.Expression> expressions1 = new ArrayList<org.owasp.appsensor.core.rule.Expression>(); | ||
expressions1.add(expression1); | ||
|
||
configuredRules.add(new Rule("00000000-0000-0000-0000-000000000011", minutes16, expressions1, responses, "Rule 1")); | ||
configuredRules.add(new Rule("00000000-0000-0000-0000-000000000011", minutes5, expressions1, responses, "Rule 1")); | ||
|
||
return configuredRules; | ||
} | ||
|
||
private static Collection<DetectionPoint> loadMockedDetectionPoints() { | ||
final Collection<DetectionPoint> configuredDetectionPoints = new ArrayList<DetectionPoint>(); | ||
|
||
ArrayList<Response> responses = generateResponses(); | ||
|
||
Interval minutes5 = new Interval(5, Interval.MINUTES); | ||
private static ArrayList<DetectionPoint> generateDetectionPoints() { | ||
ArrayList<DetectionPoint> detectionPoints = new ArrayList<DetectionPoint>(); | ||
|
||
Threshold events3minutes5 = new Threshold(3, minutes5); | ||
// dp1: 3 events in 5 minutes | ||
DetectionPoint detectionPoint1 = new DetectionPoint(); | ||
|
||
DetectionPoint point1 = new DetectionPoint(DetectionPoint.Category.INPUT_VALIDATION, "IE1", events3minutes5, responses); | ||
detectionPoint1.setCategory(DetectionPoint.Category.INPUT_VALIDATION); | ||
detectionPoint1.setLabel("IE1"); | ||
detectionPoint1.setThreshold(new Threshold(3, new Interval(5, Interval.MINUTES))); | ||
detectionPoint1.setResponses(generateResponses()); | ||
|
||
configuredDetectionPoints.add(point1); | ||
detectionPoints.add(detectionPoint1); | ||
|
||
return configuredDetectionPoints; | ||
return detectionPoints; | ||
} | ||
|
||
private static ArrayList<Response> generateResponses() { | ||
|
@@ -242,4 +249,15 @@ private static ArrayList<Response> generateResponses() { | |
return responses; | ||
} | ||
|
||
public AggregateEventAnalysisEngine getRulesEngine() { | ||
Collection<EventAnalysisEngine> engines = appSensorServer.getEventAnalysisEngines(); | ||
|
||
for (EventAnalysisEngine engine : engines) { | ||
if (engine instanceof AggregateEventAnalysisEngine){ | ||
return (AggregateEventAnalysisEngine)engine; | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.