Skip to content

Instantly share code, notes, and snippets.

@indigo423
Last active September 25, 2023 11:26
Show Gist options
  • Save indigo423/2dcce1cd74a2700640e3a4a3b94d126f to your computer and use it in GitHub Desktop.
Save indigo423/2dcce1cd74a2700640e3a4a3b94d126f to your computer and use it in GitHub Desktop.
Drools Rule for SSHD syslog password audit
<?xml version="1.0" encoding="UTF-8"?>
<engine-configuration
xmlns="http://xmlns.opennms.org/xsd/drools-engine"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.opennms.org/xsd/drools-engine /var/lib/opennms/xsds/drools-engine.xsd ">
<rule-set name="loginFailureRules">
<rule-file>LoginFailureRules.drl</rule-file>
<event>uei.opennms.org/syslogd/authpriv/Notic</event>
<app-context>loginFailureRules-context.xml</app-context>
<global name="EVENT_INTERVAL" type="java.lang.Long" value="30000" />
<global name="EVENT_COUNT" type="java.lang.Integer" value="10" />
<global name="LOG" ref="slf4jLogger"/>
</rule-set>
</engine-configuration>
<events xmlns="http://xmlns.opennms.org/xsd/eventconf">
<event>
<uei>uei.opennms.org/drools/loginaudit/breakInAttempt</uei>
<event-label>Login audit: Drools aggregated authentication failure</event-label>
<descr>&lt;p&gt;The interface %interface% generated a Syslog Message.&lt;br&gt;
Node ID: %nodeid%&lt;br&gt;
Host: %nodelabel%&lt;br&gt;
Interface: %interface% &lt;br&gt;
Message: %parm[syslogmessage]% &lt;br&gt;
Process: %parm[process]% &lt;br&gt;
PID: %parm[processid]%
&lt;/p&gt;
&lt;p&gt;All parameters: %parm[all]%&lt;/p&gt;
</descr>
<logmsg dest="logndisplay">
&lt;p&gt;Drools aggregated authentication failure event&lt;/p&gt;
Message: %parm[syslogmessage]% &lt;br&gt;
</logmsg>
<severity>Major</severity>
<alarm-data reduction-key="%uei%:%dpname%:%nodeid%:%interface%" alarm-type="3" auto-clean="false"/>
</event>
</events>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<!-- tx:annotation-driven / -->
<bean name="slf4jLogger" class="org.slf4j.LoggerFactory" factory-method="getLogger">
<constructor-arg value="Drools.Engine" />
</bean>
</beans>
package org.opennms.netmgt.correlation.drools;
import java.util.Date;
import org.opennms.core.utils.InetAddressUtils;
import org.opennms.netmgt.correlation.drools.DroolsCorrelationEngine;
import org.opennms.netmgt.xml.event.Event;
import org.opennms.netmgt.xml.event.Parm;
import org.opennms.netmgt.model.events.EventBuilder;
import org.opennms.netmgt.model.events.EventUtils;
import org.opennms.netmgt.events.api.EventConstants;
global org.opennms.netmgt.correlation.drools.DroolsCorrelationEngine engine;
global org.slf4j.Logger LOG;
global java.lang.Integer EVENT_COUNT;
global java.lang.Long EVENT_INTERVAL;
global java.lang.String UEI;
rule "first password failure event received"
salience 100
when
$e : Event( $uei : uei matches "uei.opennms.org/syslogd/authpriv/Notice", $nodeid : nodeid, $ipAddr : interface, $svcName : service )
not $flap : Flap(nodeid == $nodeid, ipAddr == $ipAddr, svcName == $svcName, locationMonitor == -1 );
then
retract( $e );
println( "Got an event: " + $uei );
insert ( createFlap(engine, $nodeid, $ipAddr, $svcName, -1, EVENT_INTERVAL ));
end
rule "Start a new flap count if we don't have one"
salience 100
when
$e : Event( $uei : uei, $nodeid : nodeid, $ipAddr : interface, $svcName : service )
$flap : Flap(nodeid == $nodeid, ipAddr == $ipAddr, svcName == $svcName, locationMonitor == -1 );
not FlapCount( nodeid == $nodeid, ipAddr == $ipAddr, svcName == $svcName, locationMonitor == -1 );
then
insert( new FlapCount( $nodeid, $ipAddr, $svcName, -1 ) );
update( $flap );
retract( $e );
end
rule "start counting events"
salience 100
lock-on-active true
when
$e : Event( $uei : uei, $nodeid : nodeid, $ipAddr : interface, $svcName : service )
$flap : Flap(nodeid == $nodeid, ipAddr == $ipAddr, svcName == $svcName, locationMonitor == -1 );
$eventCount : FlapCount( nodeid == $nodeid, ipAddr == $ipAddr, svcName == $svcName, locationMonitor == -1, $count : count );
then
$eventCount.increment();
println($uei + " count(" + $count + ")");
update( $eventCount );
update( $flap );
end
rule "retract timer-expired counters"
when
$flap : Flap( $nodeid : nodeid, $ipAddr : ipAddr, $svcName : svcName, locationMonitor == -1, $timerId : timerId )
$expiration: TimerExpired( id == $timerId )
$eventCount : FlapCount( nodeid == $nodeid, ipAddr == $ipAddr, svcName == $svcName, locationMonitor == -1 )
then
println( "Counter for " +$nodeid + ":" + $ipAddr + " has expired after " + EVENT_INTERVAL + "ms. ");
retract( $flap );
retract( $eventCount );
retract( $expiration );
end
rule "flap count exceeded, send rollup event"
when
$eventCount : FlapCount( $nodeid : nodeid, $ipAddr : ipAddr, $svcName : svcName, locationMonitor == -1, alerted == false, count >= ( EVENT_COUNT ) )
$e : Event()
then
sendRollupEvent( engine, $e, EVENT_COUNT, EVENT_INTERVAL );
println("Event count(" + EVENT_COUNT + ") exceeded for " + $e.getUei() + ", sending rollup event");
retract( $e );
$eventCount.setAlerted( true );
update( $eventCount );
end
//
// Builds the rollup event to emit when the count is exceeded
//
function void sendRollupEvent(DroolsCorrelationEngine engine, Event e, Integer count, Long interval) {
EventBuilder bldr = new EventBuilder("uei.opennms.org/drools/loginaudit/breakInAttempt", "DroolsEventAccumulator")
.setNodeid(e.getNodeid())
.setInterface(e.getInterfaceAddress())
.setService(e.getService());
copyParms(e, bldr);
bldr.addParam("rolledUpUEI", e.getUei())
.addParam("eventCount", count)
.addParam("interval", interval);
engine.sendEvent(bldr.getEvent());
}
//
// Creates the Flap object, which has the timer we need
//
function Flap createFlap(DroolsCorrelationEngine engine, Long nodeid, String ipAddr, String svcName, Integer locationMonitor, Long eventInterval) {
return new Flap( nodeid, ipAddr, svcName, locationMonitor, engine.setTimer( eventInterval ) );
}
//
// Copy parms from the last event into the Rollup event
//
function void copyParms(Event sourceEvent, EventBuilder targetEventBuilder) {
for (Parm p : sourceEvent.getParmCollection()) {
targetEventBuilder.addParam(p);
}
}
//
// Just for convenience
//
function void println(Object msg) {
System.out.println(new Date()+" : "+msg);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment