/** * Copyright 2012 Radware and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * ### class description ### * * @author Snir Cohen * @author Gera Goft * @version 0.1 */ package com.radware.defenseflow.dp; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import me.prettyprint.cassandra.serializers.StringSerializer; import org.opendaylight.defense4all.core.AMS; import org.opendaylight.defense4all.core.DFAppModule; import org.opendaylight.defense4all.core.DFAppRoot; import org.opendaylight.defense4all.core.DFAppRoot.RepoMajor; import org.opendaylight.defense4all.core.DvsnInfo; import org.opendaylight.defense4all.core.DvsnInfo.AMSDvsnInfo; import org.opendaylight.defense4all.core.interactionstructures.Bandwidth; import org.opendaylight.defense4all.core.Mitigation; import org.opendaylight.defense4all.core.PN; import org.opendaylight.defense4all.framework.core.ExceptionControlApp; import org.opendaylight.defense4all.framework.core.FrameworkMain.ResetLevel; import org.opendaylight.defense4all.framework.core.FMHolder; import org.opendaylight.defense4all.framework.core.HealthTracker; import org.opendaylight.defense4all.framework.core.Repo; import org.opendaylight.defense4all.framework.core.RepoFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.radware.defenseflow.dp.DPRep.RepoMinor; import com.radware.defenseflow.dp.pojos.Classes.Networks.Network; import com.radware.defenseflow.dp.pojos.Classes.Networks.NetworkKey; import com.radware.defenseflow.dp.pojos.Classes.Networks.Network_Mode; import com.radware.defenseflow.dp.pojos.Classes.VLANTagGroup.GroupEntry; import com.radware.defenseflow.dp.pojos.Classes.VLANTagGroup.GroupEntryKey; import com.radware.defenseflow.dp.pojos.Classes.VLANTagGroup.GroupEntry_GroupMode; import com.radware.defenseflow.dp.pojos.Management.SyslogServers.FeatureStatus; import com.radware.defenseflow.dp.pojos.Management.SyslogServers.SyslogServersTable; import com.radware.defenseflow.dp.pojos.Management.SyslogServers.SyslogServersTable_syslogServerFacility; import com.radware.defenseflow.dp.pojos.Management.SyslogServers.SyslogServersTable_syslogServerProtocol; import com.radware.defenseflow.dp.pojos.Management.SyslogServers.SyslogServersTable_syslogServerRowStatus; import com.radware.defenseflow.dp.pojos.Security.BehavioralDoS.Profiles; import com.radware.defenseflow.dp.pojos.Security.BehavioralDoS.Profiles_FINACKFloodstatus; import com.radware.defenseflow.dp.pojos.Security.BehavioralDoS.Profiles_FRAGFloodstatus; import com.radware.defenseflow.dp.pojos.Security.BehavioralDoS.Profiles_ICMPFloodstatus; import com.radware.defenseflow.dp.pojos.Security.BehavioralDoS.Profiles_IGMPFloodstatus; import com.radware.defenseflow.dp.pojos.Security.BehavioralDoS.Profiles_RSTFloodstatus; import com.radware.defenseflow.dp.pojos.Security.BehavioralDoS.Profiles_SYNACKFloodstatus; import com.radware.defenseflow.dp.pojos.Security.BehavioralDoS.Profiles_SYNFloodstatus; import com.radware.defenseflow.dp.pojos.Security.BehavioralDoS.Profiles_UDPFloodstatus; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile_DnsAFloodstatus; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile_DnsAaaaFloodstatus; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile_DnsMxFloodstatus; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile_DnsNaptrFloodstatus; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile_DnsOtherFloodstatus; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile_DnsPtrFloodstatus; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile_DnsSoaFloodstatus; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile_DnsSrvFloodstatus; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile_DnsTextFloodstatus; import com.radware.defenseflow.dp.pojos.Security.DnsProtection.DnsProtectionProfile_packetReport; import com.radware.defenseflow.dp.pojos.Security.OutOfState.Profile; import com.radware.defenseflow.dp.pojos.Security.OutOfState.Profile_PacketReport; import com.radware.defenseflow.dp.pojos.Security.OutOfState.Profile_ProfileAction; import com.radware.defenseflow.dp.pojos.Security.OutOfState.Profile_ProfileRisk; import com.radware.defenseflow.dp.pojos.Security.OutOfState.Profile_SYNACKAllow; import com.radware.defenseflow.dp.pojos.Security.Policy.Policy; import com.radware.defenseflow.dp.pojos.Security.Policy.Policy_Action; import com.radware.defenseflow.dp.pojos.Security.Policy.Policy_PacketReport; import com.radware.defenseflow.dp.pojos.Security.Policy.Policy_PacketReportEnforcement; import com.radware.defenseflow.dp.pojos.Security.SynProtection.RsIDSSynProfilesEntry; import com.radware.defenseflow.dp.pojos.Security.SynProtection.RsIDSSynProfilesEntry_ProfileType; public class DPConfigMgr extends DFAppModule { public static final String SYN_PROTECTION_PROFILE_NAME = "SYNProt_Global"; public static final String SIGNATURES_PROFILE_NAME = "Dos-All"; /* Profile name value suffixes */ public static final String BDOS_PROFILE_NAME_SUFFIX = "_BDOS"; public static final String DNS_PROFILE_NAME_SUFFIX = "_DNS"; public static final String OOS_PROFILE_NAME_SUFFIX = "_OoS"; /* Percentage of tolerable failures to configure networks in DP */ public static final int DP_NETWORKS_FAILURE_THRESHOLD = 20; public static final int DP_VLAN_FAILURE_PERCENTAGE_THRESHOLD = 10; /* DF vlan prefix*/ public static final String DF_VLAN_PREFIX = "df_vlan_"; private Logger log = LoggerFactory.getLogger(this.getClass()); public DPRep amsRep; protected HashMap<String, SoapConnector> connectors; /* * Syn profile and its name, signatures default profile name (pre-existing * in DP) */ protected Profile synProtectionProfile; protected long dnsAQuota = 90; protected long dnsMxQuota = 45; protected long dnsPtrQuota = 45; protected long dnsAaaaQuota = 15; protected long dnsTextQuota = 8; protected long dnsSoaQuota = 2; protected long dnsNaptrQuota = 2; protected long dnsSrvQuota = 2; protected long dnsOtherQuota = 2; protected long actThreshold = 5000; protected long termThreshold = 4000; /** Repos for configured networks and security configurations. */ public Repo<String> configuredNetworkRepo = null; public Repo<String> configuredVlanRepo = null; public Repo<String> securityConfigRepo = null; /** * Create DPCfgMgr object * * @param connector * @param custDnsTrafficEstimate */ public DPConfigMgr() { super(); connectors = new HashMap<String, SoapConnector>(); /* Init globally defined profiles/names */ synProtectionProfile = new Profile(); synProtectionProfile.setProfileName(SYN_PROTECTION_PROFILE_NAME); } /* Setters for Spring */ public void setAmsRep(DPRep amsRep) {this.amsRep = amsRep;} @Override public void init() throws ExceptionControlApp { super.init(); /* create/get DPConfigMgr Repos */ try { RepoFactory rf = fMain.getRepoFactory(); String rMajor = RepoMajor.DF_AMS_REP.name(); StringSerializer sSer = StringSerializer.get(); configuredNetworkRepo = (Repo<String>) rf.getOrCreateRepo(rMajor, RepoMinor.CONFIGURED_NETWORKS.name(), sSer, true, ConfiguredNetwork.getRCDs()); configuredVlanRepo = (Repo<String>) rf.getOrCreateRepo(rMajor, RepoMinor.CONFIGURED_VLANS.name(), sSer, true, ConfiguredVlan.getRCDs()); securityConfigRepo = (Repo<String>) rf.getOrCreateRepo(rMajor, RepoMinor.SECURITY_CONFIGURATIONS.name(), sSer, true, SecurityConfig.getRCDs()); } catch (Throwable e) { log.error("Failed to getOrCreateRepo for configured networks.", e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.SIGNIFICANT_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to getOrCreateRepo for configured networks.", e); } } @Override public void finit() { super.finit(); } @Override public void reset(ResetLevel resetLevel) throws ExceptionControlApp { super.reset(resetLevel); } /** * #### method description #### * * @param param_name * param description * @return return description * @throws ExceptionControlApp * @throws exception_type circumstances description */ public void addAMS(String amsKey) throws ExceptionControlApp, IllegalArgumentException { if(amsKey == null) throw new IllegalArgumentException("amsKey is null"); Hashtable<String, Object> amsRow; AMS ams; SoapConnector connector; Iterator<Map.Entry<String, Hashtable<String, Object>>> configuredNetworkIter; Iterator<Map.Entry<String, Hashtable<String, Object>>> configuredVlanIter; Hashtable<String, Hashtable<String, Object>> configuredNetworksTable; int numOfDpNetworks; int numOfDpVlans; Hashtable<String, Hashtable<String, Object>> configuredVlanTable; Set<Map.Entry<String, Hashtable<String, Object>>> entrySet; ConfiguredNetwork configuredNetwork; Hashtable<String, Object> configurationNetworkRow; ConfiguredVlan configuredVlan; Hashtable<String, Object> configurationVlanRow; Network dpNetwork = null; GroupEntry vlanGroupEntry = null; int networksFailuresCount = 0; int vlansFailuresCount = 0; try { amsRow = dfAppRoot.amsRepo.getRow(amsKey); ams = new AMS(amsRow); /* Create a connector object to this DP. */ connector = new SoapConnector(amsKey, ams.mgmtAddr.getHostAddress(), ams.username, ams.password); connector.init(); connectors.put(amsKey, connector); configuredNetworksTable = configuredNetworkRepo.getTable(); entrySet = configuredNetworksTable.entrySet(); configuredNetworkIter = entrySet.iterator(); numOfDpNetworks = entrySet.size(); configuredVlanTable = configuredVlanRepo.getTable(); entrySet = configuredVlanTable.entrySet(); configuredVlanIter = entrySet.iterator(); numOfDpVlans = entrySet.size(); } catch (Throwable e1) { connectors.remove(amsKey); // In case the exception occurred after we have added the connector to connectors String msg = "Excepted trying to retrieve or construct relevant information" + amsKey; log.error(msg, e1); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MODERATE_HEALTH_ISSUE); throw new ExceptionControlApp(msg, e1); } /* Add global profiles (applicable for all PNs). */ try { addGlobalProfilesIfNeeded(connector); } catch (Throwable e1) { connectors.remove(amsKey); // In case the exception occurred after we have added the connector to connectors String msg = "Excepted trying to add global profiles to DP" + amsKey; log.error(msg, e1); throw new ExceptionControlApp(msg, e1); } /* Add all DF instances (as of now there is only one) as DP syslog targets. */ try { addSyslogTarget(connector, fMain.getHostAddr()); } catch (Throwable e1) { connectors.remove(amsKey); } /* Add network configurations for all PNs to the newly added DP. */ log.info( "Adding to DP " + amsKey + " classes networks representing all protected networks"); while (configuredNetworkIter.hasNext()) { try { configurationNetworkRow = configuredNetworkIter.next().getValue(); configuredNetwork = new ConfiguredNetwork(configurationNetworkRow); dpNetwork = createDPNetworkObject(configuredNetwork); connector.createClassesNetworks(dpNetwork); } catch (Throwable e) { log.error("Failed to create network: " + dpNetwork, e); networksFailuresCount++; } } /* Add Vlans for all PNs to the newly added DP. */ log.info("Adding to DP " + amsKey + " Vlans spanning all protected networks"); String vlanStr = ""; while (configuredVlanIter.hasNext()) { try { vlanStr = ""; configurationVlanRow = configuredVlanIter.next().getValue(); configuredVlan = new ConfiguredVlan(configurationVlanRow); vlanGroupEntry = createSingleVlanGroup(configuredVlan.name, configuredVlan.vlan); if(vlanGroupEntry != null) { vlanStr = configuredVlan.name + " " + configuredVlan.vlan; connector.createClassesVlan(vlanGroupEntry); } } catch (Throwable e) { log.error("Failed to create vlan: " + vlanStr, e); vlansFailuresCount++; } } /* Decide whether the operation is failed based on the percentage of failed dpNetwork and vlan creations in DP. * 1 is added to avoid division by zero in case there are no configured networks/vlans (e.g., no PNs yet). */ if((networksFailuresCount * 100 / (numOfDpNetworks+ 1) < DP_NETWORKS_FAILURE_THRESHOLD) && (vlansFailuresCount * 100 / (numOfDpVlans+ 1) < DP_VLAN_FAILURE_PERCENTAGE_THRESHOLD)) return; /* Operation is failed, so try to undo all side affects (no atomicity - best effort for each undo). * We do not remove global profiles if created (treat them as part of the basic DP setup). */ FMHolder.get().getFR().logRecord(DFAppRoot.FR_AMS_FAILURE, "AMS " + amsKey + " configuration failed. Exceeded threshold"); /* Remove the newly added connector. */ connectors.remove(amsKey); /* Remove all dpNetworks, ignoring failure to remove any one of them. */ try { configuredNetworkIter = entrySet.iterator(); } catch (Throwable e1) { log.debug("Failed to obtain second iterator: " + amsKey, e1); } NetworkKey networkKey = null; while (configuredNetworkIter.hasNext()) { try { configurationNetworkRow = configuredNetworkIter.next().getValue(); configuredNetwork = new ConfiguredNetwork(configurationNetworkRow); dpNetwork = createDPNetworkObject(configuredNetwork); networkKey = new NetworkKey(configuredNetwork.name, 0); connector.deleteClassesNetwork(networkKey); } catch (Throwable e) { log.error("Failed to remove Network: " + networkKey, e); } } /* Remove all dpVlans, ignoring failure to remove any one of them. */ try { configuredVlanIter = entrySet.iterator(); } catch (Throwable e1) { log.debug("Failed to obtain second iterator: " + amsKey, e1); } GroupEntryKey groupEntryKey = null; while (configuredVlanIter.hasNext()) { try { configurationVlanRow = configuredVlanIter.next().getValue(); configuredVlan = new ConfiguredVlan(configurationVlanRow); groupEntryKey = new GroupEntryKey(); groupEntryKey.setGroupName(configuredVlan.name); groupEntryKey.setVLANTag(configuredVlan.vlan); connector.deleteClassesVlan(groupEntryKey); } catch (Throwable e) { log.error("Failed to remove vlan", e); } } /* Log and report error. */ String msg = "Failed to add this DP, because failed to configure networks or vlans for too many PNs." + amsKey; log.error(msg); throw new ExceptionControlApp(msg); } /* * Add syn protection and signatures profiles if needed. If added - reboot DP to pick up changes. */ public void addGlobalProfilesIfNeeded(SoapConnector connector) throws ExceptionControlApp { try { log.info("Adding to DP " + connector.amsKey + " global SYN profiles for HTTP and HTTPS (if needed)"); RsIDSSynProfilesEntry synProtectionProfileObject = createSynProtectionProfileObject((long)200000, "HTTP"); connector.createIfNonExistingSynProtectionProfile(synProtectionProfileObject); synProtectionProfileObject = createSynProtectionProfileObject((long)200001, "HTTPS"); connector.createIfNonExistingSynProtectionProfile(synProtectionProfileObject); } catch ( Throwable e) { String msg = "Failed to add Global Profiles: " + e.getMessage(); log.error(msg); throw new ExceptionControlApp(msg); } } /** * Add specified DF address as syslog target for the specified DP * #### method description #### * @param param_name param description * @return return description * @throws exception_type circumstances description */ public void addSyslogTarget(SoapConnector connector, String syslogTargetAddr) throws ExceptionControlApp { try { long syslogServerSourcePort = 514; long syslogServerDestinationPort = 514; SyslogServersTable syslogTarget = new SyslogServersTable(syslogTargetAddr, FeatureStatus.Enabled, syslogServerSourcePort, syslogServerDestinationPort, SyslogServersTable_syslogServerFacility.value23, SyslogServersTable_syslogServerProtocol.value1, "", SyslogServersTable_syslogServerRowStatus.reachable, null, FeatureStatus.Enabled, FeatureStatus.Enabled, FeatureStatus.Enabled); connector.addSyslogTarget(syslogTarget); } catch (Throwable e) { String msg = "Failed to add syslog target "+syslogTargetAddr+" to DP "+connector.amsKey+" - "+e.getMessage(); log.error(msg); throw new ExceptionControlApp(msg); } } private RsIDSSynProfilesEntry createSynProtectionProfileObject(long attactId, String attactName) { RsIDSSynProfilesEntry rsIDSSynProfilesEntry = new RsIDSSynProfilesEntry(); rsIDSSynProfilesEntry.setProfileName(SYN_PROTECTION_PROFILE_NAME); rsIDSSynProfilesEntry.setAttackID(attactId); rsIDSSynProfilesEntry.setAttackName(attactName); rsIDSSynProfilesEntry.setProfileType(RsIDSSynProfilesEntry_ProfileType.value2); return rsIDSSynProfilesEntry; } /** * #### method description #### * * @param param_name * param description * @return return description * @throws ExceptionControlApp * @throws exception_type circumstances description */ public void removeAMS(String amsKey) throws ExceptionControlApp, IllegalArgumentException { if(amsKey == null) throw new IllegalArgumentException("amsKey is null"); /* Create a connector object to this DP. */ SoapConnector connector = connectors.remove(amsKey); /* Remove network configurations for all PNs to the being removed DP. */ List<String> configNetworkKeys = null; try { configNetworkKeys = configuredNetworkRepo.getKeys(); } catch (Throwable e) { log.error("Failed to remove ams: " + amsKey, e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MODERATE_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to remove ams: " + amsKey, e); } NetworkKey networkKey = null; log.info( "Deleting from DP " + connector.amsKey + " all msgclasses networks that DF has installed for all protected networks"); for (String configuredNetworkName : configNetworkKeys) { try { networkKey = new NetworkKey(configuredNetworkName, 0); connector.deleteClassesNetwork(networkKey); } catch (Throwable e) { log.error("Failed to remove Network: " + networkKey, e); } } /* Remove all DF instances (as of now there is only one) as syslog targets. */ try { connector.removeSyslogTarget(fMain.getHostAddr()); } catch (Exception e) { /* Ignore */} } /** * #### method description #### * * @param param_name * param description * @return return description * @throws ExceptionControlApp * @throws exception_type * circumstances description */ public void addPN(String pnkey) throws ExceptionControlApp { Network dpNetwork = null; SoapConnector connector = null; Iterator<Map.Entry<String, SoapConnector>> connectorsIter = connectors.entrySet().iterator(); try { /* Create and populate the configuredNetwork object. */ ConfiguredNetwork configuredNetwork = new ConfiguredNetwork(); configuredNetwork.name = DPRep.generateNetworkName(pnkey); configuredNetwork.address = (String) dfAppRoot.pNsRepo.getCellValue(pnkey, PN.DST_ADDR); configuredNetwork.addressPrefixLen = (Integer) dfAppRoot.pNsRepo.getCellValue(pnkey, PN.DST_ADDR_PREFIX_LEN); /* Add the configured network to its repo. */ configuredNetworkRepo.setRow(configuredNetwork.name,configuredNetwork.toRow()); dpNetwork = createDPNetworkObject(configuredNetwork); log.info("Adding to all DPs " + configuredNetwork.toString()); } catch (Throwable e1) { String msg = "Excepted trying to add pn: " + pnkey; log.error(msg, e1); throw new ExceptionControlApp(msg, e1); } /* Pre-register the PN network in all DPs. */ while (connectorsIter.hasNext()) { try { connector = connectorsIter.next().getValue(); connector.createClassesNetworks(dpNetwork); } catch (Exception e) { log.error("Failed to create network: " + dpNetwork + " at " + (connector==null ? "" : connector.amsKey), e); } } } /** * #### method description #### * * @param param_name * param description * @return return description * @throws ExceptionControlApp * @throws exception_type * circumstances description */ public void addVlans(List<ConfiguredVlan> configuredVlans) throws ExceptionControlApp { if(configuredVlans == null || configuredVlans.isEmpty()) return; boolean anyConfiguredVlan = false; for(ConfiguredVlan configuredVlan: configuredVlans) { try { addVlan(configuredVlan); anyConfiguredVlan = true; } catch (Throwable e) {/* Ignore */} } if(!anyConfiguredVlan) throw new ExceptionControlApp("Failed to configure any Vlan in DP"); } public void addVlan(ConfiguredVlan configuredVlan) throws ExceptionControlApp { SoapConnector connector = null; GroupEntry singleVlanObject; Iterator<Map.Entry<String, SoapConnector>> connectorsIter = connectors.entrySet().iterator(); try { configuredVlanRepo.setRow(configuredVlan.name, configuredVlan.toRow()); // Add configured vlan to its repo singleVlanObject = createSingleVlanGroup(configuredVlan.name, configuredVlan.vlan); // Create DP Vlan object log.info("Adding to all DPs "+configuredVlan.toString()); } catch (Throwable e1) { String msg = "Excepted trying to add vlan: " + configuredVlan.name; log.error(msg, e1); throw new ExceptionControlApp(msg, e1); } /* Pre-register the vlan in all DPs. */ while (connectorsIter.hasNext()) { try { connector = connectorsIter.next().getValue(); connector.createClassesVlan(singleVlanObject); } catch (Exception e) { log.error("Failed to create vlan: " + configuredVlan.toString() + " at " + (connector==null ? "" : connector.amsKey), e); } } } /** * #### method description #### * * @param param_name * param description * @return return description * @throws exception_type * circumstances description */ public void removePN(String pnkey) throws IllegalArgumentException { if(pnkey == null) throw new IllegalArgumentException("Null pnkey."); /* Unregister the PN network in all DPs. */ Iterator<Map.Entry<String, SoapConnector>> iter = connectors.entrySet().iterator(); String networkName = DPRep.generateNetworkName(pnkey); NetworkKey networkKey = new NetworkKey(networkName, 0); SoapConnector connector; log.info( "Removing from all DPs " + networkKey.getName()); while (iter.hasNext()) { connector = iter.next().getValue(); connector.deleteClassesNetwork(networkKey); } /* Remove the configured network from repo */ try { configuredNetworkRepo.deleteRow(pnkey); } catch (ExceptionControlApp e) { log.error("Failed to delete row: " + pnkey, e); } } public void addSecurityConfiguration(String dvsnInfoKey) throws ExceptionControlApp { /* Retrieve/generate networkName, connector, inboundBandwidthStr, dvsnInfo, pnkey. */ Hashtable<String, Object> dvsnInfoRow = dfAppRoot.dvsnInfosRepo.getRow(dvsnInfoKey); if(dvsnInfoRow == null) { String msg = "AMS security configuration failed. No diversion information found for the logical net-node."; log.error(msg); FMHolder.get().getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp(msg); } DvsnInfo dvsnInfo = new DvsnInfo(dvsnInfoRow); if(dvsnInfo.amsDvsnInfos == null || dvsnInfo.amsDvsnInfos.isEmpty()) return; AMSDvsnInfo amsDvsnInfo = dvsnInfo.amsDvsnInfos.get(0); SoapConnector connector = connectors.get(amsDvsnInfo.label); if(connector == null) return; String inboundBandwidthStr = dvsnInfo.configProps.getProperty(DvsnInfo.INBOUND_BANDWIDTH); String pnkey = (String) dfAppRoot.mitigationsRepo.getCellValue(dvsnInfo.mitigationKey, Mitigation.PNKEY); String networkName = DPRep.generateNetworkName(pnkey); Hashtable<String,Object> pnRow = dfAppRoot.pNsRepo.getRow(pnkey); PN pn = new PN(pnRow); int vlan = pn.retrieveVlanFromProps(); /* Add the security configuration to the DP and record it in Repo. */ log.info("Adding security configuration to DP " + connector.amsKey + "for diversion " + dvsnInfoKey); addSecurityConfigInDP(networkName, connector, inboundBandwidthStr, vlan); try { addSecurityConfigInRepo(networkName, dvsnInfo, amsDvsnInfo, pnkey); } catch (Throwable e) { // Need to clean up from DP String msg ="AMS "+ connector.amsKey + " security configuration failed. Failed to configure diversion for logical net-node."; FMHolder.get().getFR().logRecord(DFAppRoot.FR_AMS_FAILURE, msg); removeSecurityConfigInDP(connector, networkName); log.error(msg, e); throw new ExceptionControlApp(e); } } protected void removeSecurityConfigInDP(SoapConnector connector, String networkName) { connector.deletePolicy(networkName); connector.deleteBdosProfile(networkName + BDOS_PROFILE_NAME_SUFFIX); boolean dnsEnabled = false; try { connector.deleteDnsProfile(networkName + DNS_PROFILE_NAME_SUFFIX); } catch (RuntimeException e) { if(dnsEnabled) { log.warn("failed to delete DNS profile"); throw e; } else { log.debug("failed to delete DNS profile, not error or warning, since DNS is disabled"); } } connector.deleteOosProfile(networkName + OOS_PROFILE_NAME_SUFFIX); } /** * #### method description #### * @param dnsProfileCreated * * @param param_name * param description * @return return description * @throws ExceptionControlApp * @throws exception_type circumstances description */ public void addSecurityConfigInDP(String networkName, SoapConnector connector, String inboundBandwidthStr, int vlan) throws ExceptionControlApp { long bandwidthKbps = 0; Bandwidth bandwidth; try { bandwidth = new Bandwidth(inboundBandwidthStr); bandwidthKbps = bandwidth.bytes * 8 / 1000; bandwidthKbps = bandwidthKbps < 1 ? 1 : bandwidthKbps; } catch (Throwable e) { log.error("Failed to calculate bandwidth, " + e.getMessage(), e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp("Failed to calculate bandwidth, " + e.getMessage()); } /* Create all the security profiles and policy for this attacked PN. */ String bdosProfileName = null; String dnsProfileName = null; String oosProfileName = null; //boolean bdosProfileCreated = false; //boolean dnsProfileCreated = false; //boolean oosProfileCreated = false; try { // long custDnsTrafficEstimate = 0; long custDnsTrafficEstimate = 5000; bdosProfileName = networkName + BDOS_PROFILE_NAME_SUFFIX; dnsProfileName = networkName + DNS_PROFILE_NAME_SUFFIX; oosProfileName = networkName + OOS_PROFILE_NAME_SUFFIX; log.info("Calculated bandwidth for BDoS profile: "+bandwidthKbps); Profiles bdosProfile = createBdosProfile(bdosProfileName, bandwidthKbps); DnsProtectionProfile dnsProfile = createDnsProfile(dnsProfileName, custDnsTrafficEstimate); Profile oosProfile = createOutOfStateProfile(oosProfileName); boolean dnsEnabled = false; try { dnsEnabled = connector.updateCreateDnsProfile(dnsProfile); if(!dnsEnabled) dnsProfileName = null; } catch (Throwable e) { dnsProfileName = null; // Indicate to createPolicy not to include dns profile, since its creation failed. } /* Create the vlan Object in DP prior to referring to it in the policy. */ String vlanName = DF_VLAN_PREFIX + vlan +1; GroupEntry vlanObj = createSingleVlanGroup(vlanName, vlan); log.warn("skipping creation of VLAN "+vlanName); vlanName = null; // try { // connector.createClassesVlan(vlanObj); // } catch(Throwable e1) {vlanName = null;} Policy securityPolicy = createPolicy(networkName,bdosProfileName,dnsProfileName,oosProfileName,vlanName); /* Set in DP all created profiles and policy for this attacked PN. */ connector.updateCreateBdosProfile(bdosProfile); //bdosProfileCreated = true; connector.updateCreateOOSProfile(oosProfile); //oosProfileCreated = true; connector.updateCreatePolicy(securityPolicy); } catch (Throwable e) { //Don't need to be removed it do update instead // if(bdosProfileCreated && bdosProfileName != null) connector.deleteBdosProfile(bdosProfileName); // if(dnsProfileCreated && bdosProfileName != null) connector.deleteDnsProfile(bdosProfileName); // if(oosProfileCreated && oosProfileName != null) connector.deleteOosProfile(oosProfileName); log.error("Failed to add security configuration, " + e.getMessage(), e); throw new ExceptionControlApp("Failed to add security configuration: " + e.getMessage()); } } private void addSecurityConfigInRepo(String networkName, DvsnInfo dvsnInfo, AMSDvsnInfo amsDvsnInfo, String pnkey) throws ExceptionControlApp { /* Check if the security configuration already exists in repo (could be registered with another DP). If so - * update that record with this DP. Otherwise create the record in the repo with this DP. */ boolean setInAmsRepo = false; String secConfigKey = ""; try { String bdosProfileName = networkName + BDOS_PROFILE_NAME_SUFFIX; String dnsProfileName = networkName + DNS_PROFILE_NAME_SUFFIX; String oosProfileName = networkName + OOS_PROFILE_NAME_SUFFIX; secConfigKey = SecurityConfig.generateKey(networkName, dvsnInfo.mitigationKey); dfAppRoot.amsRepo.setCell(amsDvsnInfo.label, AMS.SECURITY_CONFIG_PREFIX + secConfigKey, secConfigKey); setInAmsRepo = true; if (securityConfigRepo.hasCell(secConfigKey,SecurityConfig.NETWORK_NAME)) // Means this security config was already set for other DPs - so add this one securityConfigRepo.setCell(secConfigKey,SecurityConfig.DP_NAME_PREFIX + amsDvsnInfo.label, amsDvsnInfo.label); else { // Need to create new security record and add to repo SecurityConfig securityConfig = new SecurityConfig(); securityConfig.mitigationKey = dvsnInfo.mitigationKey; securityConfig.pnkey = pnkey; securityConfig.configuredNetworkName = networkName; securityConfig.bdosProfileName = bdosProfileName; securityConfig.dnsProfileName = dnsProfileName; securityConfig.oosProfileName = oosProfileName; securityConfig.securityPolicyName = networkName; securityConfig.generateAndSetKey(); securityConfig.configuredDPs = new ArrayList<String>(); securityConfig.configuredDPs.add(amsDvsnInfo.label); securityConfigRepo.setRow(secConfigKey, securityConfig.toRow()); } } catch (Throwable e) { if(setInAmsRepo) { try { dfAppRoot.amsRepo.deleteCell(amsDvsnInfo.label, AMS.SECURITY_CONFIG_PREFIX + secConfigKey); } catch (Throwable e1) {/* Ignore. */} } String msg = "Failed to add security configuration in database"; log.error(msg, e); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); throw new ExceptionControlApp(msg + e.getMessage()); } // We do not currently address the need to book-keep preparing for multiple diversions into for the same PN into // the same DP. This means that: 1. In case of dual attempt to set up profiles and policy for the same PN we // ignore DP's rejection to setup. 2. We do not update the bandwidth to account for diversion from another netnode. } /** * #### method description #### * * @param param_name param description * @return return description * @throws ExceptionControlApp * @throws exception_type circumstances description */ public void removeSecurityConfiguration(String dvsnInfoKey) { String amsKey = "."; try { DvsnInfo dvsnInfo = DvsnInfo.getDvsnInfo(dvsnInfoKey); String amsDvsnInfoLabel = dvsnInfo.amsDvsnInfos.get(0).label; SoapConnector connector = connectors.get(amsDvsnInfoLabel); String pnkey = (String) dfAppRoot.mitigationsRepo.getCellValue(dvsnInfo.mitigationKey, Mitigation.PNKEY); String networkName = DPRep.generateNetworkName(pnkey); String securityConfigKey = SecurityConfig.generateKey(networkName, dvsnInfo.mitigationKey); amsKey = connector.amsKey; String msg = "Removing security configuration from AMS " + amsKey + " for mitigation of " + Mitigation.getPrintableMitigationTarget(dvsnInfo.mitigationKey); FMHolder.get().getFR().logRecord(DFAppRoot.FR_AMS_SECURITY, msg); List<Mitigation> allPNMitigations = dfAppRoot.getMitigationMgr().getAllPNMitigations(pnkey); Boolean toRemove = true; for (Mitigation currentMitigation : allPNMitigations ) { try { if ( currentMitigation.status != Mitigation.Status.ACTIVE ) continue; for ( String currentDvsnInfoKey :currentMitigation.dvsnInfoKeys ) { if ( currentDvsnInfoKey.equals(dvsnInfoKey)) continue; DvsnInfo currentDvsnInfo = DvsnInfo.getDvsnInfo(currentDvsnInfoKey); String currentAmsDvsnInfoLabel = currentDvsnInfo.amsDvsnInfos.get(0).label; if ( currentAmsDvsnInfoLabel.equals(amsDvsnInfoLabel)) { toRemove = false; } } } catch (Exception e) { continue; } } if ( toRemove) removeSecurityConfigInDP(connector, networkName); /* Remove the securityConfig from its repo. Also delete the securityConfigKey from AMS repo. */ securityConfigRepo.deleteRow(securityConfigKey); dfAppRoot.amsRepo.deleteCell(amsDvsnInfoLabel, AMS.SECURITY_CONFIG_PREFIX + securityConfigKey); } catch (Throwable e) { String msg = "Failed to fully remove security configuration from AMS " +amsKey; log.error(msg, e); FMHolder.get().getFR().logRecord(DFAppRoot.FR_DF_FAILURE, msg); fMain.getHealthTracker().reportHealthIssue(HealthTracker.MINOR_HEALTH_ISSUE); } // We do not currently address the need to book-keep preparing for multiple diversions into for the same PN into // the same DP. This means that in case of dual attempt to remove profiles and policy at the end of an attack we // ignore DP rejection. } public Network createDPNetworkObject(ConfiguredNetwork configuredNetwork) { Network network = new Network(); network.setName(configuredNetwork.name); network.setIndex(0); network.setAddress(configuredNetwork.address); network.setMask(Integer.toString(configuredNetwork.addressPrefixLen)); network.setMode(Network_Mode.value1); // value1 = "IP Mask"; value2 = "IP Range" return network; } public Network createDPNetworkObject(String address, String mask, String name) { Network network = new Network(); network.setName(name); network.setIndex(1); network.setAddress(address); network.setMask(mask); network.setMode(Network_Mode.value2); return network; } private Profiles createBdosProfile(String bdosProfileName, long bandwidth) { Profiles profile = new Profiles(); profile.setProfileName(bdosProfileName); profile.setBandwidthIn(bandwidth); profile.setBandwidthOut(bandwidth); profile.setSYNACKFloodstatus(Profiles_SYNACKFloodstatus.active); profile.setSYNFloodstatus(Profiles_SYNFloodstatus.active); // profile.setTransparentOptimization(Profiles_TransparentOptimization.yes); profile.setUDPFloodstatus(Profiles_UDPFloodstatus.active); profile.setICMPFloodstatus(Profiles_ICMPFloodstatus.active); profile.setIGMPFloodstatus(Profiles_IGMPFloodstatus.active); profile.setFINACKFloodstatus(Profiles_FINACKFloodstatus.active); profile.setFRAGFloodstatus(Profiles_FRAGFloodstatus.active); profile.setRSTFloodstatus(Profiles_RSTFloodstatus.active); return profile; } private DnsProtectionProfile createDnsProfile(String dnsProfileName, long custDnsTrafficEstimate) { DnsProtectionProfile profile = new DnsProtectionProfile(); profile.setProfileName(dnsProfileName); profile.setDnsAFloodstatus(DnsProtectionProfile_DnsAFloodstatus.active); profile.setDnsMxFloodstatus(DnsProtectionProfile_DnsMxFloodstatus.active); profile.setDnsPtrFloodstatus(DnsProtectionProfile_DnsPtrFloodstatus.active); profile.setDnsAaaaFloodstatus(DnsProtectionProfile_DnsAaaaFloodstatus.active); profile.setDnsTextFloodstatus(DnsProtectionProfile_DnsTextFloodstatus.active); profile.setDnsSoaFloodstatus(DnsProtectionProfile_DnsSoaFloodstatus.active); profile.setDnsNaptrFloodstatus(DnsProtectionProfile_DnsNaptrFloodstatus.active); profile.setDnsSrvFloodstatus(DnsProtectionProfile_DnsSrvFloodstatus.active); profile.setDnsOtherFloodstatus(DnsProtectionProfile_DnsOtherFloodstatus.active); profile.setExpectedQps(custDnsTrafficEstimate); profile.setDnsAQuota(dnsAQuota); profile.setDnsMxQuota(dnsMxQuota); profile.setDnsPtrQuota(dnsPtrQuota); profile.setDnsAaaaQuota(dnsAaaaQuota); profile.setDnsTextQuota(dnsTextQuota); profile.setDnsSoaQuota(dnsSoaQuota); profile.setDnsNaptrQuota(dnsNaptrQuota); profile.setDnsSrvQuota(dnsSrvQuota); profile.setDnsOtherQuota(dnsOtherQuota); profile.setMaxAllowedQPS(custDnsTrafficEstimate * 2); profile.setPacketReport(DnsProtectionProfile_packetReport.enable); return profile; } private Profile createOutOfStateProfile(String oosProfileName) { Profile profile = new Profile(); profile.setProfileName(oosProfileName); profile.setACTThreshold(actThreshold); profile.setTermThreshold(termThreshold); profile.setSYNACKAllow(Profile_SYNACKAllow.enable); profile.setProfileRisk(Profile_ProfileRisk.medium); profile.setProfileAction(Profile_ProfileAction.value2); profile.setPacketReport(Profile_PacketReport.enable); return profile; } @SuppressWarnings("unused") private GroupEntry createVlanGroup(String groupName, long vlanTag, long vlanTagRangeFrom, Long vlanTagRangeTo) { GroupEntry groupEntry = new GroupEntry(groupName, vlanTag, vlanTagRangeFrom, vlanTagRangeTo, GroupEntry_GroupMode.Range); return groupEntry; } private GroupEntry createSingleVlanGroup(String groupName, long vlanTag) { GroupEntry groupEntry = new GroupEntry(groupName, 65536, vlanTag, vlanTag, GroupEntry_GroupMode.Range); return groupEntry; } public Policy createPolicy(String networkName, String bdosProfileName,String dnsProfileName, String oosProfileName, String vlanGroupName) { Policy policy = new Policy(); policy.setPolicyName(networkName); policy.setPolicyDestinationAddress(networkName); policy.setPolicySourceAddress("any"); policy.setBehavioralDosProfile(bdosProfileName); if(dnsProfileName != null) policy.setDNSProtectionProfile(dnsProfileName); policy.setSynProtectionProfile(synProtectionProfile.getProfileName()); policy.setOutOfStateProfile(oosProfileName); policy.setAction(Policy_Action.value2); policy.setPacketReport(Policy_PacketReport.enable); policy.setPacketReportEnforcement(Policy_PacketReportEnforcement.enable); if(vlanGroupName != null) policy.setVlanTagGroup(vlanGroupName); return policy; } @Override protected void actionSwitcher(int actionCode, Object param) { } }