/**
* Copyright 2012 Radware and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* ### class description ###
*
* @author Gera Goft
* @version 0.1
*/
package com.radware.defenseflow.dp;
import java.net.UnknownHostException;
import java.util.Hashtable;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.opendaylight.defense4all.core.DFAppModule;
import org.opendaylight.defense4all.core.DFAppRoot;
import org.opendaylight.defense4all.core.DFHolder;
import org.opendaylight.defense4all.core.Detection;
import org.opendaylight.defense4all.core.Detector;
import org.opendaylight.defense4all.core.DetectorInfo;
import org.opendaylight.defense4all.core.Mitigation;
import org.opendaylight.defense4all.core.ProtocolPort;
import org.opendaylight.defense4all.core.Detection.DetectionConfidence;
import org.opendaylight.defense4all.framework.core.ExceptionControlApp;
import org.opendaylight.defense4all.framework.core.FrameworkMain.ResetLevel;
import org.opendaylight.defense4all.framework.core.HealthTracker;
public class DPBasedDetector extends DFAppModule implements Detector {
/**
* DPBasedDetectionEngine Repo types
*/
public static final int TYPE_INVALID = -1;
public static final int TYPE_RESERVED = 0;
/**
* Minimal time to keep the diversion going so the attack is not mistakingly ended in case DP is out for some time
*/
public static final int MINIMAL_ATTACK_DURATION = 600;
/**
* Decoupled actions for ActionSwitcher
*/
protected static final int ACTION_INVALID = -1; // Already defined in Module. Brought here for brevity
protected static final int ACTION_RESERVED = 0; // Already defined in Module. Brought here for brevity
protected static final int ACTION_ADD_DETECTION = 1;
Logger log = LoggerFactory.getLogger(this.getClass());
protected boolean initialized = false;
DetectorInfo detectorInfo;
protected DPRep dpRep = null;
protected int durationOfDetection = 300;
/* Detectors Repo column names */
public static final String DURATION_OF_DETECTION = "duration_of_detection";
public DPBasedDetector() {
super();
}
/* Setters for Spring */
public void setDpRep(DPRep dpRep) {this.dpRep = dpRep;}
public void setDetectorInfoStr(String detectorInfoStr) {
try {
detectorInfo = new DetectorInfo(detectorInfoStr);
} catch (IllegalArgumentException e) {
log.error("Incorrect detectorInfoStr " + detectorInfoStr);
}
detectorInfo.ofBasedDetector = false;
detectorInfo.externalDetector = false;
}
public void setLabel ( String label ) {
detectorInfo.setLabel(label);
}
public void setDurationOfDetection(int duration) {this.durationOfDetection = duration;}
/** Post-constructor initialization
* @throws Exception */
public void init() throws ExceptionControlApp {
super.init();
try {
DFHolder.get().getDetectorMgr().addDetector(this); // Register to support PNs with DP-based detection
} catch (ExceptionControlApp e) {
log.error("Excepted trying to register the dpBasedDetector at detectors manager.", e);
fMain.getHealthTracker().reportHealthIssue(HealthTracker.MODERATE_HEALTH_ISSUE);
throw e;
}
initialized = true;
}
/** Pre-shutdown cleanup */
public void finit() {
super.finit();
}
/** Reset
* @throws ExceptionControlApp */
public void reset(ResetLevel resetLevel) throws ExceptionControlApp {
super.reset(resetLevel);
}
/**
* #### method description ####
* @param param_name param description
* @return return description
* @throws ExceptionControlApp
* @throws UnknownHostException
*/
public void addMonitoredAttack(String mitigationKey) {
/* Register initial DP-based "detection" until DP indications start flowing */
long currentTime = System.currentTimeMillis() / 1000;
Hashtable<String, Object> mitigationRow; Mitigation mitigation;
try {
mitigationRow = dfAppRoot.mitigationsRepo.getRow(mitigationKey);
mitigation = new Mitigation(mitigationRow);
} catch (Throwable e) {
log.error("Excepted trying to retrieve mitigationRow or inflate mitigation " + mitigationKey, e);
//FMHolder.get().getFR().logRecord(DFAppRoot.FR_DF_FAILURE, "Failed to add monitored through DPs traffic "
// + "for mitigation " + mitigationKey);
fMain.getHealthTracker().reportHealthIssue(HealthTracker.MODERATE_HEALTH_ISSUE);
return;
}
String detectionKey = Detection.generateDetectionKey(detectorInfo.label, mitigation.pnKey, mitigation.protocolPort);
Detection detection = new Detection(detectionKey, detectorInfo.label, DetectionConfidence.VERY_HIGH,
currentTime, durationOfDetection, mitigation.pnKey, mitigation.protocolPort);
try {
invokeDecoupledSerially(ACTION_ADD_DETECTION, detection);
} catch (ExceptionControlApp e) {
log.error("Excepted trying to invokeDecoupledSerialiy " + ACTION_ADD_DETECTION + " " + detectionKey, e);
return;
}
}
/**
* #### method description ####
* @param param_name param description
* @return return description
* @throws exception_type circumstances description
*/
public void removeMonitoredAttack(String mitigationKey) {
; // No op
}
/**
* #### method description ####
* @param param_name param description
* @return return description
* @throws exception_type circumstances description
*/
public void addPN(String pnKey) {
}
/**
* #### method description ####
* @param param_name param description
* @return return description
* @throws exception_type circumstances description
*/
public void removePN(String pnKey) {
}
protected void decoupledAddDetection(Detection detection) {
dfAppRoot.getAttackDecisionPoint().addDetection(detection);
}
/**
* #### method description ####
* @param param_name param description
* @return return description
* @throws exception_type circumstances description
*/
public void handleAttackReport(AttackReport attackReport) {
/* Check attack status. Can be occur, start, ongoing, sampled, term. Anything except "term" will trigger
* attack detection update. */
if(attackReport.dpSecEvent.attackStatus.equals("term")) {
log.info("DP attack termination syslog" + attackReport.toString());
fMain.getFR().logRecord(DFAppRoot.FR_DF_SECURITY, "Received \"attack terminated\" indication from DP.");
return; // Fade out attack detection
}
/* If there is already a diversion for this attack then update its runtime properties */
updateDvsnExecutionProps(attackReport.monitoredTraffic.mitigationKey, attackReport.dpSecEvent);
/* Tell AttackDecisionPoint that the attack is still on */
String pnKey = attackReport.monitoredTraffic.pnKey;
DPSecEvent dpSecEvent = attackReport.dpSecEvent;
ProtocolPort protocolPort = new ProtocolPort(dpSecEvent.dpProtocol.toDFProtocol(), dpSecEvent.dstPort);
String detectionKey = Detection.generateDetectionKey(detectorInfo.label, pnKey, protocolPort);
Detection detection = new Detection(detectionKey, detectorInfo.label, DetectionConfidence.VERY_HIGH,
attackReport.reportTime, durationOfDetection, pnKey, protocolPort);
try {
invokeDecoupledSerially(ACTION_ADD_DETECTION, detection);
} catch (ExceptionControlApp e) {
log.error("Excepted trying to invokeDecoupledSerialiy " + ACTION_ADD_DETECTION + " " + detectionKey, e);
}
}
/**
* #### method description ####
* @param param_name param description
* @return return description
* @throws exception_type circumstances description
*/
public void updateDvsnExecutionProps(String mitigationKey, DPSecEvent dpSecEvent) {
/* All the premature returns are because there is apparently no diversion (yet) for this attack)*/
if(mitigationKey == null) return;
Properties dvsnExecProps = null;
try {
dvsnExecProps = (Properties) dfAppRoot.mitigationsRepo.getCellValue(mitigationKey, Mitigation.MITIGATION_EXECUTION_PROPS);
if(dvsnExecProps == null) return;
/* Set the latest diversion execution properties */
dvsnExecProps.setProperty(DPSecEvent.SEVERITY_PROPERTY, dpSecEvent.severity);
dvsnExecProps.setProperty(DPSecEvent.RADWARE_EVENT_TYPE_ID_PROPERTY, String.valueOf(dpSecEvent.rdwrEventTypeId));
dvsnExecProps.setProperty(DPSecEvent.CATEGORY_PROPERTY, dpSecEvent.category);
dvsnExecProps.setProperty(DPSecEvent.ATTACK_NAME_PROPERTY, dpSecEvent.attackName);
dvsnExecProps.setProperty(DPSecEvent.CONTEXT_PROPERTY, dpSecEvent.context);
dvsnExecProps.setProperty(DPSecEvent.POLICY_NAME_PROPERTY, dpSecEvent.policyName);
dvsnExecProps.setProperty(DPSecEvent.ATTACK_STATUS_PROPERTY, dpSecEvent.attackStatus);
dvsnExecProps.setProperty(DPSecEvent.PACKET_COUNT_PROPERTY, String.valueOf(dpSecEvent.packetCount));
dvsnExecProps.setProperty(DPSecEvent.ATTACK_BANDWIDTH_PROPERTY, String.valueOf(dpSecEvent.attackBandwidth));
dvsnExecProps.setProperty(DPSecEvent.RISK_PROPERTY, dpSecEvent.risk);
dvsnExecProps.setProperty(DPSecEvent.ACTION_PROPERTY, dpSecEvent.action);
dvsnExecProps.setProperty(DPSecEvent.EVENT_GUID_PROPERTY, dpSecEvent.eventGuid);
/* Set the updated diversion execution properties back to repo */
dfAppRoot.mitigationsRepo.setCell(mitigationKey, Mitigation.MITIGATION_EXECUTION_PROPS, dvsnExecProps);
} catch (ExceptionControlApp e) {
log.error("Excepted trying to updateDvsnExecutionProps for " + mitigationKey, e);
fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE);
return;
}
}
public DetectorInfo getDetectorInfo() {return detectorInfo;}
public String getDetectorInfoStr() {return detectorInfo.toString();}
/**
* Compose detector repository row
*/
public Hashtable<String, Object> toRow() {
Hashtable<String, Object> row = detectorInfo.toRow();
row.put(DPBasedDetector.DURATION_OF_DETECTION ,durationOfDetection);
return row;
}
public void fromRow(Hashtable<String, Object> row) {
this.detectorInfo.fromRow(row);
Object durationOfDetectionObj = row.get(DPBasedDetector.DURATION_OF_DETECTION);
if(durationOfDetectionObj != null) durationOfDetection = (Integer) durationOfDetectionObj;
}
@Override
protected void actionSwitcher(int actionCode, Object param) {
switch(actionCode) {
case ACTION_RESERVED:
break;
case ACTION_ADD_DETECTION:
decoupledAddDetection((Detection) param);
break;
default:
break;
}
}
}