package com.cloudera.sa.node360.service.utils;
import com.cloudera.sa.node360.model.EventPojo;
import com.cloudera.sa.node360.model.NetFlowPojo;
import com.cloudera.sa.node360.model.NotificationPojo;
import org.apache.commons.lang.StringUtils;
import org.apache.mina.util.ConcurrentHashSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by ted.malaska on 6/13/15.
*/
public class SecurityRulesWrapper {
public static ConcurrentHashMap<ByteArrayWrapper, ConcurrentHashMap<ByteArrayWrapper, HistoricalTimes>> scrNodeToDestNodeMap =
new ConcurrentHashMap<ByteArrayWrapper, ConcurrentHashMap<ByteArrayWrapper, HistoricalTimes>>();
public static List<NotificationPojo> processEvents(List<EventPojo> events) {
List<NotificationPojo> notificationPojos = new ArrayList<NotificationPojo>();
for (EventPojo event: events) {
if (event.getType().equals(EventPojo.NETFLOW_TYPE)) {
ByteArrayWrapper nodeBytes = convertIpToBytes(event.getNode());
ConcurrentHashMap<ByteArrayWrapper, HistoricalTimes> byteSet =
scrNodeToDestNodeMap.get(nodeBytes);
if (byteSet == null) {
byteSet = new ConcurrentHashMap<ByteArrayWrapper, HistoricalTimes>();
scrNodeToDestNodeMap.put(nodeBytes, byteSet);
}
for (NetFlowPojo netFlowPojo : event.getNetFlowPojoList()) {
final ByteArrayWrapper byteArrayWrapper = convertIpToBytes(netFlowPojo.getDestinationAddress());
HistoricalTimes historicalTimes = byteSet.get(byteArrayWrapper);
if (historicalTimes == null) {
String noteString = "Behavior anomaly - " + netFlowPojo.getSourceAddress() + " has new connection to new host " + netFlowPojo.getDestinationAddress();
notificationPojos.add(new NotificationPojo(event.getTimestamp(),
noteString, System.currentTimeMillis() - event.getTimestamp()));
byteSet.put(byteArrayWrapper, new HistoricalTimes(event.getTimestamp(), 0));
} else {
if (historicalTimes.applyNewTimeStamp(event.getTimestamp())) {
String noteString = "Potential APT - Beaconing { scrNode:" + event.getNode() + ", destNode:"
+ netFlowPojo.getDestinationAddress() + ", intervalTime:" + historicalTimes.getLastInterval() + "}";
notificationPojos.add(new NotificationPojo(event.getTimestamp(),
noteString, System.currentTimeMillis() - event.getTimestamp()));
}
}
}
}
}
return notificationPojos;
}
public static ByteArrayWrapper convertIpToBytes(String node) {
String[] parts = StringUtils.split(node, '.');
byte[] nodeBytes = new byte[4];
nodeBytes[0] = Byte.parseByte(parts[0]);
nodeBytes[1] = Byte.parseByte(parts[1]);
nodeBytes[2] = Byte.parseByte(parts[2]);
nodeBytes[3] = Byte.parseByte(parts[3]);
return new ByteArrayWrapper(nodeBytes);
}
public static final class ByteArrayWrapper
{
private final byte[] data;
public ByteArrayWrapper(byte[] data)
{
if (data == null)
{
throw new NullPointerException();
}
this.data = data;
}
@Override
public boolean equals(Object other)
{
if (!(other instanceof ByteArrayWrapper))
{
return false;
}
return Arrays.equals(data, ((ByteArrayWrapper) other).data);
}
@Override
public int hashCode()
{
return Arrays.hashCode(data);
}
}
public static final class HistoricalTimes {
long lastTimeStamp;
long lastInterval;
public HistoricalTimes(long lastTimeStamp, long lastInterval) {
this.lastTimeStamp = lastTimeStamp;
this.lastInterval = lastInterval;
}
public boolean applyNewTimeStamp(long newTimeStamp) {
long newDiff = newTimeStamp - lastTimeStamp;
if (newDiff > 2) {
boolean match = (newDiff == lastInterval);
lastTimeStamp = newTimeStamp;
lastInterval = newDiff;
return match;
} else {
return false;
}
}
public long getLastTimeStamp() {
return lastTimeStamp;
}
public void setLastTimeStamp(long lastTimeStamp) {
this.lastTimeStamp = lastTimeStamp;
}
public long getLastInterval() {
return lastInterval;
}
public void setLastInterval(long lastInterval) {
this.lastInterval = lastInterval;
}
}
}