/** * Copyright (c) <2013> <Radware Ltd.> and others. All rights reserved. * * This program and the accompanying materials are made available under the terms of the Eclipse Public License * v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html * @author Gera Goft * @author Konstantin Pozdeev * @version 0.1 */ package org.opendaylight.defense4all.core.impl; import java.io.IOException; import java.io.InputStream; import java.lang.IllegalArgumentException; import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import javax.transaction.NotSupportedException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opendaylight.defense4all.core.AMS; import org.opendaylight.defense4all.core.Attack; import org.opendaylight.defense4all.core.DFAppRoot; import org.opendaylight.defense4all.core.DFDetector; import org.opendaylight.defense4all.core.DFMgmtPoint; import org.opendaylight.defense4all.core.Detector; import org.opendaylight.defense4all.core.DetectorInfo; import org.opendaylight.defense4all.core.NetNode; import org.opendaylight.defense4all.core.OFC; import org.opendaylight.defense4all.core.PN; import org.opendaylight.defense4all.core.PN.OperationalStatus; import org.opendaylight.defense4all.core.PN.StatsCollectionStatus; import org.opendaylight.defense4all.core.interactionstructures.PNStatReport; import org.opendaylight.defense4all.framework.core.ExceptionControlApp; import org.opendaylight.defense4all.framework.core.HealthTracker; import org.opendaylight.defense4all.framework.core.FrameworkMain.ResetLevel; /** * TODO: description - app focal point. orchestrates start, stop. */ public class DFMgmtPointImpl extends DFAppCoreModule implements DFMgmtPoint { /** * DFMgmtPoint Repo types */ public static final int TYPE_INVALID = -1; public static final int TYPE_RESERVED = 0; private static Log log = LogFactory.getLog(DFMgmtPointImpl.class); public DFMgmtPointImpl() { super(); } /** * Initialize after construction. Look for an OFC to add - first check in repo if one has already been set in * previous life cycle. If not, check if one has been set through Spring. * @throws Exception * @throws exception_type circumstances description */ public void init() throws ExceptionControlApp { super.init(); log.info("DefenseFlow management failed in initialize."); /* OFC related initializations. */ List<String> ofcKeys = null; try { ofcKeys = dfAppRoot.oFCsRepo.getKeys(); } catch (Throwable e) { log.error("Failed to get keys from oFCsRepo ", e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow management failed in initialize."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get keys from oFCsRepo ", e ); } if ( ofcKeys == null) { log.error("Invalid null oFCsRepo"); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow management failed in initialize."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MODERATE_HEALTH_ISSUE); throw new ExceptionControlApp("Invalid null oFCsRepo"); } if(ofcKeys.size() > 0) { try { addOFC(ofcKeys.get(0)); } catch (Throwable e) { // TODO Currently Ignore, but need to account for regular init vs. reset init log.error("Failed to re-add OFC " + ofcKeys.get(0), e); } } /* AMS related initializations. */ List<String> amsKeys; try { amsKeys = dfAppRoot.amsRepo.getKeys(); } catch (Exception e1) { log.error("Failed to get keys from amsRepo ", e1 ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow management failed in initialize."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get keys from amsRepo ", e1 ); } if ( amsKeys == null) { log.debug ("Invalid null amsRepo"); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow management failed in initialize."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MODERATE_HEALTH_ISSUE); throw new ExceptionControlApp("Invalid null oFCsRepo"); } for(int i=0; i<amsKeys.size();i++) // Re-register all AMSs if not there yet addAMS(amsKeys.get(i)); /* NetNode related initializations. */ List<String> netNodeKeys; try { netNodeKeys = dfAppRoot.netNodesRepo.getKeys(); } catch (Throwable e3) { log.error("Failed to get keys from amsRepo ", e3 ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow management failed in initialize."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get keys from netNodesRepo ", e3); } if ( netNodeKeys == null) { log.debug ("Invalid null netNodesRepo"); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow management failed in initialize."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MODERATE_HEALTH_ISSUE); throw new ExceptionControlApp("Invalid null netNodesRepo"); } /* Re-register all NetNodes if not there yet, except those marked as removed. */ for(String netNodeLabel : netNodeKeys) { try { if(NetNode.isRemoved(netNodeLabel)) dfAppRoot.netNodesRepo.deleteRow(netNodeLabel); else addNetNode(netNodeLabel); } catch (Throwable e) {continue; /* Ignore */} } /* PN related initializations. */ List<String> pnKeys; try { pnKeys = dfAppRoot.pNsRepo.getKeys(); } catch (Throwable e5) { log.error("Failed to get keys from pNsRepo ", e5 ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow management failed in initialize."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get keys from pNsRepo ", e5 ); } if ( pnKeys == null) { log.debug ("Invalid null pNsRepo"); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow management failed in initialize."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MODERATE_HEALTH_ISSUE); throw new ExceptionControlApp("Invalid null oFCsRepo"); } for(int i=0; i<pnKeys.size();i++) { // Re-register all protected networks in controller if not there yet try { addPN(pnKeys.get(i)); } catch (Throwable e) { log.error("Failed to re-add PN " + pnKeys.get(i), e); } } try { if(pnKeys.size() == 0) { // Add PN if one set through properties file. Next time PN will be in repo. loadAndSetPNsFromPropsFile(); } } catch (Throwable e6) { log.error("Failed to create PN from default parameters ", e6); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow management failed in initialize."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to create PN from default parameters ", e6 ); } } /** * Cleanup before shutdown * @throws exception_type circumstances description */ public void finit() { log.info("DFMgmtPoint is stopping."); super.finit(); } /** Reset * @throws ExceptionControlApp */ public void reset(ResetLevel resetLevel) throws ExceptionControlApp { log.info("DFMgmtPoint is resetting to level " + resetLevel); super.reset(resetLevel); resetPns(resetLevel); } protected void loadAndSetPNsFromPropsFile() throws Exception { // Read properties file with default PNs attributes Properties propsFromFile = new Properties(); Properties pnFields = new Properties(); InputStream is=DFMgmtPointImpl.class.getClassLoader().getResourceAsStream("pns.properties"); try { propsFromFile.load(is); } catch(IOException ioExc) { log.warn("DF failed to instantiate PN from properties file.", ioExc); try { is.close(); } catch (IOException e) {/* Ignore */} return; } try { is.close(); } catch (IOException e) {/* Ignore */} String pnLabels = propsFromFile.getProperty("PN.pns"); if(pnLabels == null || pnLabels.isEmpty()) return; PN defaultPN = new PN(); Set<String> pnKeySet = defaultPN.toRow().keySet(); Properties pnProps; Properties pnAmsProps; Set<Object> propsFromFileKeySet; String propFromFileKey; String pnAttributeKey; String[] split; String propFromFile; int amsPropertyPrefixLen = PN.AMS_PROPERTY_PREFIX.length(); List<String> netNodes = new ArrayList<String>(); /* Set each property for relevant pn in the props file - either into its attribute or * into the props attribute (can be in case properties of PN sub-classes are set) */ String[] pnLabelsSplit; try { pnLabelsSplit = pnLabels.split(","); } catch (Exception e) { log.error("Invalid lead line(PN.pns) in pns.properties file", e); //fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DF failed to instantiate PN from properties file."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Invalid lead line(PN.pns) in pns.properties file", e); } for( String pnLabel : pnLabelsSplit ) { try { pnProps = new Properties(); pnAmsProps = new Properties(); propsFromFileKeySet = propsFromFile.keySet(); for ( Object keyObject : propsFromFileKeySet ) { propFromFileKey = (String) keyObject; split = propFromFileKey.split("\\."); if(split.length < 3) continue; if(!split[1].equals(pnLabel)) continue; pnAttributeKey = split[2]; propFromFile = propsFromFile.getProperty(propFromFileKey); if (pnKeySet.contains(pnAttributeKey)) pnFields.setProperty(pnAttributeKey, propFromFile); else if(pnAttributeKey.startsWith(PN.AMS_PROPERTY_PREFIX)) pnAmsProps.setProperty(pnAttributeKey.substring(amsPropertyPrefixLen), propFromFile); else if(pnAttributeKey.startsWith(PN.NETNODE_PREFIX)) netNodes.add(propFromFile); else pnProps.setProperty(pnAttributeKey, propFromFile); } // construct new PN from hash of attributes PN pn = new PN(pnFields, pnProps, pnAmsProps, netNodes); // Set type of detection from registered detector Detector pnDetector = dfAppRootFullImpl.detectorMgrImpl.getDetector(pn.getDetectorLabel()); if ( pnDetector != null ) { pn.setOfBasedDetection ( pnDetector.getDetectorInfo().getOfBasedDetector() ); } addPN(pn); } catch (Exception e) { log.error("Failed to create PN from pns.properties file", e); //fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DF failed to instantiate PN from properties file."); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); continue; } } } protected void resetPns(ResetLevel resetLevel) throws ExceptionControlApp { Hashtable<String, Hashtable<String, Object>> pnTable; try { pnTable = dfAppRootFullImpl.pNsRepo.getTable(); } catch (Throwable e) { log.error("Failed to get pNsRepo table", e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MODERATE_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get pNsRepo table", e); } Set<Entry<String, Hashtable<String, Object>>> pnTableEntrySet = pnTable.entrySet(); if (pnTableEntrySet == null ) return; Iterator<Map.Entry<String,Hashtable<String,Object>>> iter = pnTableEntrySet.iterator(); Map.Entry<String,Hashtable<String,Object>> entry; String pnKey; PN pn; while(iter.hasNext()) { try { entry = iter.next(); pnKey = entry.getKey(); } catch (Exception e1) { log.error("Invalid entry in pNsRepo table", e1); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); continue; } try { pn = new PN(entry.getValue()); } catch (ExceptionControlApp e) {continue; /* Ignore */} pn.averageStr = ""; pn.latestRateStr = ""; pn.latestRateTime = 0; pn.attackSuspicions = ""; pn.statsCollectionStatus = StatsCollectionStatus.INVALID; if(resetLevel == ResetLevel.dynamic) { pn.baselineStr = ""; pn.baselinesTime = 0; } try { dfAppRootFullImpl.pNsRepo.setRow(pnKey, pn.toRow()); } catch (Throwable e) { log.error("Failed to set pnRow in pNsRepo table "+pnKey, e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); continue; } } } protected void removeCanceledPns() throws ExceptionControlApp { List<String> pnkeys; try { pnkeys = dfAppRootFullImpl.pNsRepo.getKeys(); if(pnkeys == null) return; } catch (Throwable e) { log.error("Failed to get pNsRepo keys", e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MODERATE_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get pNsRepo keys", e); } for(String pnkey : pnkeys) { try { removePnIfCanceled(pnkey); } catch (Throwable e1) {continue;} } } protected void removePnIfCanceled (String pnkey) throws ExceptionControlApp { try { Object obj = dfAppRootFullImpl.pNsRepo.getCellValue(pnkey, PN.OPERATIONAL_STATUS); OperationalStatus operationalStatus = OperationalStatus.INVALID; if(obj != null) operationalStatus = OperationalStatus.valueOf((String) obj); if(operationalStatus == OperationalStatus.CANCELED) dfAppRootFullImpl.pNsRepo.deleteRow(pnkey); } catch (Throwable e) { log.error("Failed to delete pnRow in pNsRepo table "+pnkey, e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to remove canceled PN " + pnkey, e); } } /** * Add OFC according to its purpose - collection or dvsn (the same OFC can be set for both). Ignore if * already set (currently we accept only one). * @param param_name param description * @return return description * @throws ExceptionControlApp * @throws exception_type circumstances description */ @Override public void addOFC(OFC ofc) throws ExceptionControlApp, IllegalArgumentException { try { ofc.validate(); } catch (Exception e1) {throw new IllegalArgumentException(e1);} List<String> keys; fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DefenseFlow adding a controller. "); try { keys = dfAppRootFullImpl.oFCsRepo.getKeys(); } catch (Throwable e) { log.error("Failed to get keys from oFCsRepo.",e); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to add controller " + ofc.hostname); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get keys from oFCsRepo." , e ); } if(keys.size() != 0) { fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow currently supports only one controller. Controller " + ofc.hostname + " was not added."); return; // Already have a set OFC. Currently there can be only one OFC in the system. } try { dfAppRootFullImpl.oFCsRepo.setRow(ofc.hostname, ofc.toRow()); // Record ofc in ofcs repo. } catch (Throwable e) { log.error("Failed to set row to oFCsRepo. "+ ofc.hostname,e); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to add controller " + ofc.hostname); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to set row to oFCsRepo. "+ ofc.hostname,e); } try { addOFC(ofc.hostname); // Notify relevant DF modules. } catch (Throwable e) { log.error("Failed to add OFC "+ofc.hostname, e); try { dfAppRootFullImpl.oFCsRepo.deleteRow(ofc.hostname); // Rollback } finally { throw new ExceptionControlApp("Failed to add OFC " + ofc.hostname, e); } } } /** * Add OFC that has already been recorded in ofcs repo. Add according to its purpose - collection or dvsn * (the same OFC can be set for both). Ignore if already set (currently we accept only one). * @param param_name param description * @return return description * @throws exception_type circumstances description */ protected void addOFC(String ofcKey) throws ExceptionControlApp { Boolean forStatsCollection = false; Boolean forDvsn= false; boolean isError = false; ExceptionControlApp concatException = new ExceptionControlApp(""); try { forStatsCollection = (Boolean) dfAppRootFullImpl.oFCsRepo.getCellValue(ofcKey, OFC.FOR_STATS_COLLECTION); forDvsn = (Boolean) dfAppRootFullImpl.oFCsRepo.getCellValue(ofcKey, OFC.FOR_DIVERSION); } catch (Throwable e) { log.error("Failed to get cells from oFCsRepo. ofcKey : "+ ofcKey,e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get cells from oFCsRepo. ofcKey : " +ofcKey, e ); } if(forStatsCollection) { try { dfAppRootFullImpl.getStatsCollectionRep().addOFC(ofcKey); int interval = dfAppRootFullImpl.getStatsCollectionRep().getStatsCollectionInterval(); dfAppRootFullImpl.statsCollectorImpl.startCollection(interval); } catch (Throwable e1) { log.error("Failed to add OFC to StatsCollectionRep. ofcKey : "+ ofcKey,e1); try { dfAppRootFullImpl.getStatsCollectionRep().removeOFC(ofcKey);//Rollback } finally { concatException = new ExceptionControlApp("Failed to add OFC to StatsCollectionRep. ofcKey : " + ofcKey, concatException); isError = true; } } } if(forDvsn) { try { dfAppRootFullImpl.getDvsnRep().addOFC(ofcKey); } catch (Throwable e2) { log.error("Failed to add OFC to DvsnRep. ofcKey : "+ ofcKey,e2); try{ dfAppRootFullImpl.getDvsnRep().removeOFC(ofcKey);//rollback } finally { concatException = new ExceptionControlApp("Failed to add OFC to DvsnRep. ofcKey : " + ofcKey, concatException); } } } if (isError ) throw concatException; } /** * Remove OFC. The application will attempt to contact the previously set OFC in order to remove all monitors set through it. * @param param_name param description * @return return description * @throws ExceptionControlApp * @throws exception_type circumstances description */ @Override public void removeOFC(String ofcLabel) throws ExceptionControlApp { fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DefenseFlow removing controller " + ofcLabel); String ofcKey=ofcLabel; // get from repo boolean forStatsCollection = false; // retrieve from repo boolean forDvsn = false; // retrieve from repo ExceptionControlApp concatException = new ExceptionControlApp(""); boolean isError = false; try { forStatsCollection = (Boolean) dfAppRootFullImpl.oFCsRepo.getCellValue(ofcKey, OFC.FOR_STATS_COLLECTION); forDvsn = (Boolean) dfAppRootFullImpl.oFCsRepo.getCellValue(ofcKey, OFC.FOR_DIVERSION); } catch (Throwable e) { log.error("Failed to get cells from oFCsRepo. ofcKey : "+ ofcKey,e); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove controller " + ofcLabel); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get cells from oFCsRepo. ofcKey : " +ofcKey, e ); } if(forStatsCollection) { try { dfAppRootFullImpl.getStatsCollectionRep().removeOFC(ofcKey); } catch (Throwable e1) { log.error("Failed to remove OFC from StatsCollectionRep. ofcKey : "+ ofcKey,e1); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove controller " + ofcLabel); concatException = new ExceptionControlApp ("Failed to remove OFC from StatsCollectionRep. ofcKey : "+ ofcKey,concatException); } } if(forDvsn) { try { dfAppRootFullImpl.getDvsnRep().removeOFC(ofcKey); } catch (Throwable e2) { log.error("Failed to remove OFC from DvsnRep. ofcKey : "+ ofcKey,e2); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove controller " + ofcLabel); concatException = new ExceptionControlApp ("Failed to remove OFC from DvsnRep. ofcKey : "+ ofcKey,concatException); } } if (!isError ) { dfAppRootFullImpl.oFCsRepo.deleteRow(ofcKey); } else { throw concatException; } } /** * Add netNode. Notify statsCollectionRep and DvsnRep. * @param param_name param description * @return return description * @throws NotSupportedException * @throws exception_type circumstances description */ @Override public void addNetNode(NetNode netNode) throws ExceptionControlApp, IllegalArgumentException, IllegalStateException, NotSupportedException { try { netNode.validate(); } catch (Exception e1) {throw new IllegalArgumentException(e1);} Hashtable<String, Object> netNodeRow; try { netNodeRow = dfAppRootFullImpl.pNsRepo.getRow(netNode.label); } catch (Throwable e) { log.error("Failed to get netNodeRow from netNodesRepo ", e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to add NetNode " + netNode.label); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("DF Failed to process addition of netNode " + netNode.label, e ); } if(netNodeRow != null) { NetNode.Status netNodeStatus = NetNode.Status.valueOf((String) netNodeRow.get(NetNode.STATUS)); if(netNodeStatus == NetNode.Status.REMOVED) { try { dfAppRootFullImpl.netNodesRepo.deleteRow(netNode.label); } catch(Throwable e1) { log.error("Failed to delete netNodeRow from netNodesRepo ", e1 ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to add NetNode " + netNode.label); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to delete netNodeRow from netNodesRepo ", e1 ); } } else { String msg = "NetNode " + netNode.label + " is already defined. Need to delete it first"; fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DefenseFlow failed to add NetNode "+netNode.label+". Illegal argument(s)."); throw new IllegalStateException(msg); } } fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DefenseFlow adding NetNode " + netNode.label); try { dfAppRootFullImpl.netNodesRepo.setRow(netNode.label, netNode.toRow()); // Record netNode in netNodes repo. } catch (Exception e) { log.error("Failed to setRow in netNodesRepo "+netNode.label, e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to add NetNode " + netNode.label); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to setRow in netNodesRepo "+netNode.label, e ); } addNetNode(netNode.label); // Notify relevant DF modules. } /** * Add netNode that has already been recorded in netNodes repo. Notify statsCollectionRep and DvsnRep. * @param param_name param description * @return return description * @throws NotSupportedException * @throws exception_type circumstances description */ protected void addNetNode(String netNodeKey) throws ExceptionControlApp, NotSupportedException { boolean isError = false; ExceptionControlApp concatException = new ExceptionControlApp(""); try { dfAppRootFullImpl.getStatsCollectionRep().addNetNode(netNodeKey); } catch (NotSupportedException e) { throw e; // Not supported so abort addNetNode processing and throw this exception } catch (Throwable e) { log.error("Failed to update StatsCollectionRep", e); concatException = new ExceptionControlApp ("Failed to update StatsCollectionRep", concatException ); isError = true; } try { dfAppRootFullImpl.getDvsnRep().addNetNode(netNodeKey); } catch (NotSupportedException e) { try { dfAppRootFullImpl.getStatsCollectionRep().removeNetNode(netNodeKey); } catch (Throwable e1) {/* Ignore */} throw e; // Not supported so abort addNetNode processing and throw this exception } catch (Throwable e) { log.error("Failed to update DvsnRep", e); concatException = new ExceptionControlApp ("Failed to update DvsnRep", concatException ); isError = true; } try { dfAppRoot.netNodesRepo.setCell(netNodeKey, NetNode.STATUS, NetNode.Status.ACTIVE.name()); } catch (Throwable e) { log.error("Failed to update netNodesRepo", e); concatException = new ExceptionControlApp ("Failed to update netNodesRepo", concatException ); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); isError = true; } try { dfAppRootFullImpl.mitigationMgrImpl.addNetNode(netNodeKey); } catch (Throwable e) { log.error("Failed to update mitigationMgr", e); concatException = new ExceptionControlApp ("Failed to update mitigationMgrImpl", concatException ); isError = true; } if (isError) throw concatException; // TODO: Need to undo completed actions } /** * Remove netNode. The application will attempt to remove all traffic counting/diversion elements set in it. * @param param_name param description * @return return description * @throws exception_type circumstances description */ @Override public void removeNetNode(String netNodeLabel) throws ExceptionControlApp, NotSupportedException { fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DefenseFlow removing NetNode " + netNodeLabel); boolean isError = false; if(NetNode.isRemoved(netNodeLabel)) return; // Check if is already marked as removed. ExceptionControlApp concatException = new ExceptionControlApp(""); try { dfAppRootFullImpl.getDvsnRep().removeNetNode(netNodeLabel); } catch (NotSupportedException e) { throw e; // Not supported so abort removeNetNode processing and throw this exception } catch (IllegalStateException e1) { throw e1; // NetNode cannot be removed at this time/state - abort removeNetNode processing and throw this exception } catch (Throwable e2) { log.error("Failed to update DvsnRep", e2); concatException = new ExceptionControlApp ("Failed to update DvsnRep", concatException ); isError = true; } try { dfAppRootFullImpl.getStatsCollectionRep().removeNetNode(netNodeLabel); } catch (NotSupportedException e) { throw e; // Not supported so abort removeNetNode processing and throw this exception } catch (Throwable e) { log.error("Failed to update StatsCollectionRep", e); concatException = new ExceptionControlApp ("Failed to update StatsCollectionRep", concatException ); isError = true; } if (isError) { fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove NetNode " + netNodeLabel); throw concatException; } try { dfAppRoot.netNodesRepo.setCell(netNodeLabel, NetNode.STATUS, NetNode.Status.REMOVED.name()); } catch (Throwable e) { log.error("Failed to update netNodesRepo", e); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove NetNode " + netNodeLabel); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp ("Failed to update netNodesRepo", e ); } } /** * Add DP. If it is for stats collection need to notify the DP-based detector. If it is for dvsn, * notify both the dvsn rep and the DP rep. * @param param_name param description * @return return description * @throws exception_type circumstances description */ @Override public void addAMS(AMS ams) throws ExceptionControlApp, IllegalArgumentException { try { ams.validate(); } catch (Exception e1) {throw new IllegalArgumentException(e1);} fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DefenseFlow adding AMS " + ams.label); Hashtable<String,Object> amsRow = dfAppRootFullImpl.amsRepo.getRow(ams.label); if(amsRow != null) { AMS.Status status = AMS.Status.valueOf((String) amsRow.get(AMS.STATUS)); if(status == AMS.Status.REMOVED) { try { dfAppRootFullImpl.amsRepo.deleteRow(ams.label); } catch (Throwable e) { log.error("Failed to delete amsRow from amsRepo ", e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to add AMS " + ams.label); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to delete pnRow from pNsRepo ", e ); } } else { String msg = "AMS " + ams.label + " is already defined. Need to delete it first"; fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DefenseFlow failed to add AMS "+ams.label+". An AMS with the same label already exists."); throw new IllegalArgumentException(msg); } } try { dfAppRootFullImpl.amsRepo.setRow(ams.label, ams.toRow()); } catch (ExceptionControlApp e) { log.error("Failed to row to amsRepo "+ams.label, e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to add AMS " + ams.label); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to add AMS "+ams.label, e ); } if("Other".equalsIgnoreCase(ams.getBrand())){//Value from GUI dfAppRootFullImpl.setAmsRepByType("DefaultAms");//default from Spring xml } else { dfAppRootFullImpl.setAmsRepByType("DP");//DP configuration from Spring xml } addAMS(ams.label); } /** * #### description #### * @param param_name param description * @return return description * @throws exception_type circumstances description */ protected void addAMS(String amsKey) throws ExceptionControlApp { try { dfAppRootFullImpl.amsRep.addAMS(amsKey); } catch (ExceptionControlApp e) { log.error("Failed to add AMS "+amsKey, e ); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to add AMS "+amsKey, e ); } } /** * #### description #### * @param param_name param description * @return return description * @throws exception_type circumstances description */ @Override public boolean removeAMS(String amsLabel) throws ExceptionControlApp { fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DF is removing AMS " + amsLabel); if(AMS.isRemoved(amsLabel)) return true; // Check if is already marked as removed. boolean success = dfAppRootFullImpl.mitigationMgrImpl.removeAMS(amsLabel); if(!success) return false; try { dfAppRootFullImpl.amsRep.removeAMS(amsLabel); } catch (ExceptionControlApp e) { log.error("Failed to remove AMS "+amsLabel, e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DF failed to properly remove AMS " + amsLabel); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("DefenseFlow failed to remove AMS "+amsLabel, e ); } try { dfAppRoot.amsRepo.setCell(amsLabel, AMS.STATUS, AMS.Status.REMOVED.name()); } catch (Throwable e) { log.error("Failed to update netNodesRepo", e); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove AMS " + amsLabel); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp ("Failed to update netNodesRepo", e ); } return true; } /**through * Add an external detector. * @param param_name param description * @return return description * @throws exception_type circumstances description */ public void addDetector(DetectorInfo detectorInfo) throws ExceptionControlApp { fr.logRecord(DFAppRoot.FR_DF_CONFIG, " DefenseFlow adding "+detectorInfo.label+" detector "); try { if ( detectorInfo.getExternalDetector() == true) { ExternalDetector externalDetector = new ExternalDetector(detectorInfo); dfAppRootFullImpl.detectorMgrImpl.addDetector(externalDetector); } } catch (Throwable e) { log.error("Failed to add detector "+detectorInfo.label, e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to add "+detectorInfo.label+" detector "); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to add detector "+detectorInfo.label, e ); } } /** * Remove an external detector. * @param param_name param description * @return return description * @throws exception_type circumstances description */ public void removeDetector(String detectorLabel) throws ExceptionControlApp { fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DF is removing detector " + detectorLabel); try { dfAppRootFullImpl.detectorMgrImpl.removeDetector(detectorLabel); } catch (Throwable e) { log.error("Failed to remove detector "+detectorLabel, e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove "+detectorLabel+" detector "); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to remove detector "+detectorLabel, e ); } } /** * Add protected object. The protection profile referred in the protected object is assumed to be set in the system earlier. * If OFC monitoring has been specified then DF will add the object to the OFC monitored objects. * If DP based monitoring (then DP should be specified) DF will accept attack detections against the protected object * from registered DPs. In any case DF will mitigate attacks against this protected object. * For NEC vlan and array of vExtNames can be passed in the otherProperties of the ProtectedNetwork object rather than consumed from topology. * @param param_name param description * @return return description * @throws Exception * @throws ExceptionProtectionProfileNotFound If the protection profile specified in the protected object is not found in the system */ public void addPN(PN pn) throws Exception, IllegalArgumentException, IllegalStateException { try { pn.validate(); } catch (Exception e1) {throw new IllegalArgumentException(e1);} Hashtable<String, Object> pnRow; try { pnRow = dfAppRootFullImpl.pNsRepo.getRow(pn.label); } catch (Throwable e) { log.error("Failed to get pnRow from pNsRepo ", e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to add PO " + PN.getPrintableKey(pn.label)); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get pnRow from pNsRepo ", e ); } if(pnRow != null) { PN existingPn = new PN(pnRow); if(existingPn.operationalStatus == OperationalStatus.CANCELED) { try { removePnIfCanceled(existingPn.label); } catch(ExceptionControlApp e1) {throw e1;} } else { String msg = "Protected network " + pn.label + " is already defined. Need to delete it first"; fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DefenseFlow failed to add PO " + PN.getPrintableKey(pn.label)); throw new IllegalStateException(msg); } } fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DefenseFlow adding PO " + PN.getPrintableKey(pn.label)); try { dfAppRootFullImpl.pNsRepo.setRow(pn.label, pn.toRow()); } catch (Throwable e) { log.error("Failed to create pnRow from pNsRepo. pn label "+pn.label, e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to add PO " + PN.getPrintableKey(pn.label)); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to create pnRow from pNsRepo. pn label "+pn.label, e ); } addPN(pn.label); } /** * Add protected object. The protection profile referred in the protected object is assumed to be set in the system earlier. * If OFC monitoring has been specified then DF will add the object to the OFC monitored objects. * If DP based monitoring (then DP should be specified) DF will accept attack detections against the protected object * from registered DPs. In any case DF will mitigate attacks against this protected object. * For NEC vlan and array of vExtNames can be passed in the otherProperties of the ProtectedNetwork object rather than consumed from topology. * @param param_name param description * @return return description * @throws Exception * @throws ExceptionProtectionProfileNotFound If the protection profile specified in the protected object is not found in the system */ protected void addPN(String pnKey) throws ExceptionControlApp { /* Don't try to add cancelled PN */ try { Object obj = dfAppRootFullImpl.pNsRepo.getCellValue(pnKey, PN.OPERATIONAL_STATUS); OperationalStatus operationalStatus = OperationalStatus.INVALID; if(obj != null) operationalStatus = OperationalStatus.valueOf((String) obj); if(operationalStatus == OperationalStatus.CANCELED ) return; } catch (Throwable e) { log.error("Failed to retrieve operational status value for " + pnKey, e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); return; } /* Reset the PN status to INVALID - to re-attempt its installation after restarts. */ try { dfAppRootFullImpl.pNsRepo.setCell(pnKey, PN.OPERATIONAL_STATUS, PN.OperationalStatus.INVALID.name()); } catch (Throwable e) { log.error("Failed to set PN operational status for "+pnKey, e ); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to set PN operational status for "+pnKey, e); } String detectorLabel; try { detectorLabel = (String) dfAppRoot.pNsRepo.getCellValue(pnKey, PN.DETECTOR_LABEL); } catch (Throwable e) { log.error("Failed to get detectorLabel from pNsRepo for pnKey "+pnKey, e ); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get detectorLabel from pNsRepo for pnKey "+pnKey, e); } try { dfAppRootFullImpl.mitigationMgrImpl.addPN(pnKey); Detector detector = dfAppRootFullImpl.detectorMgrImpl.getDetector(detectorLabel); if ( detector != null) { boolean ofBasedDetector = detector.getDetectorInfo().ofBasedDetector; dfAppRoot.pNsRepo.setCell(pnKey, PN.OF_BASED_DETECTION, ofBasedDetector); // Base on detector, not client param detector.addPN(pnKey); } } catch (Throwable e) { log.error("Failed to add PN to detector and/or mitigation manager", e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to add PN to detector and/or mitigation manager", e); } } /** * #### method description #### * @param param_name param description * @return return description * @throws exception_type circumstances description */ @Override public Collection<PNStatReport> getLatestPNStatReports() throws ExceptionControlApp { DFDetector dfDetector; Collection<PNStatReport> pnStatReports = new ArrayList<PNStatReport>(); Collection<PNStatReport> detectorPnStatReports = new ArrayList<PNStatReport>(); /* Add pnStatReports from all OF detectors. */ try { List<Detector> detectors = dfAppRootFullImpl.detectorMgrImpl.getDetectors(); for(Detector detector : detectors) { if (!detector.getDetectorInfo().ofBasedDetector) continue; dfDetector = (DFDetector) detector; detectorPnStatReports = dfDetector.getLatestPNStatReports(); pnStatReports.addAll(detectorPnStatReports); } } catch (Throwable e) { log.error("Failed to getLatestPNStatReports ", e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to getLatestPNStatReports ", e); } return pnStatReports; } /** * #### method description #### * @param param_name param description * @return return description * @throws exception_type circumstances description */ @Override public PNStatReport getLatestPNStatReport(String pnKey) throws ExceptionControlApp, IllegalArgumentException { if(pnKey == null || pnKey.isEmpty()) throw new IllegalArgumentException("Invalid pnkey " + pnKey); String detectorLabel; Detector detector; DFDetector dfDetector; PNStatReport pnStatReport = new PNStatReport(); pnStatReport.pnKey = pnKey; /* Get the label of the detector processing stats for this PN. */ try { detectorLabel = (String) dfAppRoot.pNsRepo.getCellValue(pnKey, PN.DETECTOR_LABEL); if (detectorLabel == null) return pnStatReport; } catch (Throwable e) { log.error("Failed to get detectorLabel from pNsRepo for pnKey " + pnKey, e ); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get detectorLabel from pNsRepo for pnKey " + pnKey, e); } /* Out of the detector label get the detector processing stats for this PN. */ try { detector = dfAppRootFullImpl.detectorMgrImpl.getDetector(detectorLabel); if (detector == null) return pnStatReport; boolean ofBasedDetector = detector.getDetectorInfo().ofBasedDetector; if(!ofBasedDetector) return pnStatReport; dfDetector = (DFDetector) detector; } catch (Throwable e) { log.error("Failed to get detector " + detectorLabel, e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get detector " + detectorLabel, e); } /* Retrieve and return the PN stats from that detector. */ pnStatReport = dfDetector.getLatestPNStatReport(pnKey); return pnStatReport; } /** * #### method description #### * @param param_name param description * @return return description * @throws exception_type circumstances description */ public void changePN(PN pn) { // No Op at this time. } /** * #### method description #### * @param param_name param description * @return return description * @throws exception_type circumstances description */ public boolean removePN(String pnLabel) throws ExceptionControlApp { fr.logRecord(DFAppRoot.FR_DF_CONFIG, "DefenseFlow removing PO " + PN.getPrintableKey(pnLabel)); String pnKey = pnLabel; boolean isError = false; ExceptionControlApp concatException = new ExceptionControlApp(""); Hashtable<String, Object> pnRow; try { pnRow = dfAppRootFullImpl.pNsRepo.getRow(pnKey); } catch (ExceptionControlApp e1) { log.error("Failed to get pnRow from pNsRepo for pnKey "+pnKey, e1 ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove PO " + PN.getPrintableKey(pnLabel)); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to get pnRow from pNsRepo for pnKey "+pnKey, e1 ); } if (pnRow == null ) { fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove PO " + PN.getPrintableKey(pnLabel)); throw new ExceptionControlApp("Protected network " + pnLabel + " is unknown."); } Object obj = pnRow.get(PN.OPERATIONAL_STATUS); OperationalStatus operationalStatus = OperationalStatus.INVALID; if(obj != null) operationalStatus = OperationalStatus.valueOf((String) obj); if(operationalStatus == OperationalStatus.CANCELED) return true; try { String detectorLabel = (String) dfAppRoot.pNsRepo.getCellValue(pnKey, PN.DETECTOR_LABEL); Detector detector = dfAppRootFullImpl.detectorMgrImpl.getDetector(detectorLabel); if ( detector != null) detector.removePN(pnKey); } catch (Throwable e1) { log.error("Failed to remove PN from detector. PN key "+pnKey, e1); concatException = new ExceptionControlApp ("Failed to remove PN from detector. PN key "+pnKey, concatException); isError = true; } try { dfAppRootFullImpl.attackDecisionPointImpl.removePN(pnKey); } catch (Throwable e1) { String msg = "Failed to remove PN from attackDecisionPointImpl. PN key "+pnKey; log.error(msg, e1); concatException = new ExceptionControlApp (msg, concatException); isError = true; } try { dfAppRootFullImpl.mitigationMgrImpl.removePN(pnKey); } catch (Throwable e1) { log.error("Failed to remove PN from mitigationMgr. PN key "+pnKey, e1); concatException = new ExceptionControlApp ("Failed to remove PN from mitigationMgr. PN key "+pnKey, concatException); isError = true; } try { dfAppRoot.pNsRepo.setCell(pnKey, PN.OPERATIONAL_STATUS, PN.OperationalStatus.CANCELED.name()); } catch (Throwable e) { log.error("Failed to update pNsRepo for pnKey "+pnKey, e ); fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove PO " + PN.getPrintableKey(pnLabel)); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to update pNsRepo for pnKey "+pnKey, e ); } if (isError) { fr.logRecord(DFAppRoot.FR_DF_FAILURE, "DefenseFlow failed to remove PO " + PN.getPrintableKey(pnLabel)); throw concatException; } // Cannot remove the PN yet because the above methods are asynchronous return true; } protected boolean hasActiveAttacks(String pnKey) { List<String> attackKeys = null; try { attackKeys = dfAppRootFullImpl.attacksRepo.getKeys(); } catch (ExceptionControlApp e) { log.error("Failed to get keys from attacksRepo", e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); } if ( attackKeys == null ) return false; String attackPnKey; for(String attackKey : attackKeys) { try { attackPnKey = (String) dfAppRootFullImpl.attacksRepo.getCellValue(attackKey, Attack.PNKEY); if(attackPnKey.equals(pnKey)) return true; // Found attack on this PN } catch (ExceptionControlApp e) { log.error("Failed in hasActiveAttacks. Attack key: "+attackKey); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); } } return false; } @Override protected void actionSwitcher(int actionCode, Object param) {} public void test() { } }