package adt.mainnode.service; import adt.mainnode.dto.Asset; import adt.mainnode.dto.HostDto; import adt.mainnode.dto.PortDto; import adt.mainnode.dto.ScanInfoDto; import adt.mainnode.entity.*; import adt.mainnode.identity.HostIdentity; import adt.mainnode.identity.ScanInfoIdentity; import adt.mainnode.identity.PortIdentity; import adt.mainnode.identity.SnapshotIdentity; import adt.mainnode.repository.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.apache.commons.codec.digest.DigestUtils; import java.util.Date; import java.util.ArrayList; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import java.io.InputStreamReader; import java.io.BufferedReader; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.fasterxml.jackson.databind.*; import org.json.JSONObject; import com.fasterxml.jackson.core.JsonProcessingException; import java.io.FileWriter; import java.io.IOException; import java.util.List; import java.util.Set; import java.util.ArrayList; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.springframework.web.servlet.view.tiles3.SpringWildcardServletTilesApplicationContext; import adt.mainnode.entity.changed.*; import adt.mainnode.service.SendToURLService; @Service @Slf4j public class AssetService { private final HostRepository hostRepository; private final PortRepository portRepository; private final NodeRepository nodeRepository; private final ScanInfoRepository scanInfoRepository; private final SnapshotRepository snapshotRepository; private final VlanRepository vlanRepository; private final InitializeService initializeService; private final SendToURLService sendToURLService; @Value("${main.ip}") private String mainIP; private List urls; @Autowired public AssetService(SendToURLService sendToURLService, NodeRepository nodeRepository, HostRepository hostRepository, InitializeService initializeService, PortRepository portRepository, ScanInfoRepository scanInfoRepository, SnapshotRepository snapshotRepository, VlanRepository vlanRepository){//, VlanSnapRepository vlanSnapRepository) { this.hostRepository = hostRepository; this.portRepository = portRepository; this.scanInfoRepository = scanInfoRepository; this.snapshotRepository = snapshotRepository; this.vlanRepository = vlanRepository; this.nodeRepository = nodeRepository; this.initializeService = initializeService; this.sendToURLService = sendToURLService; this.urls = new ArrayList(); } public void setUrls(List urls){ this.urls = urls; } public List getUrls(){ return this.urls; } public void saveAssets(Asset asset, Credentials credential) { List allScans = asset.getScanInfo(); Date mainNode_timestamp = new Date(); String generatedHash = DigestUtils.sha256Hex(DigestUtils.sha256Hex(mainNode_timestamp.toString()) + DigestUtils.sha256Hex(allScans.get(0).getIniTimestampScan().toString()) + DigestUtils.sha256Hex(allScans.get(0).getEndTimestampScan().toString()) + System.currentTimeMillis()); SnapshotChange snapChange = evaluateChanges(allScans, mainNode_timestamp, asset.getDiscoveryMethod()); // TODO: retrieve from web form instead of hard-coding it here //List urlList = new ArrayList<>(); //urlList.add("http://95.168.171.182:8506/service/scan"); //urlList.add("http://138.4.130.6:12004/curex/snapshot/"); if(urls.size() > 0 && snapChange != null) { sendToURLService.processEvent(urls, snapChange); } for(int j=0; j host_dtos = scanInfo.getHost(); List hosts = new ArrayList<>(); for (int i = 0; i < host_dtos.size(); i++) { HostIdentity hostIdentity = HostIdentity.createHostIdentity(host_dtos.get(i).getIp(), scanInfoDto.getVlanName()/*vlanName*/, generatedHash); Host host = Host.createHost(hostIdentity, host_dtos.get(i)); hosts.add(host); List ports = host_dtos.get(i).getPorts().parallelStream() .map(portDto -> { PortIdentity portIdentity = PortIdentity.createPortIdentity(portDto.getPortNumber(), host.getIp(), host.getVlanName(), generatedHash); return Port.createPort(portIdentity, portDto); }) .collect(Collectors.toList()); hostRepository.save(host); portRepository.saveAll(ports); } ////// snapshotRepository.save(snapshot); scanInfoRepository.save(scanInfo); // WRITING SCAN INFO ENTITY TO FILE FOR ITS POSTERIOR UPLOAD TO VIRTUOSO'S DB ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); Object o = scanInfo; JSONObject json = null; try { json = new JSONObject(ow.writeValueAsString(o)); }catch (JsonProcessingException e){ // Handled exception } if(json != null) { String myFile = "./curexRDF/result_formatted.json"; try (FileWriter file = new FileWriter(myFile, false)) { file.write(json.toString()); file.write("\n\n"); System.out.println("Successfully Copied JSON Object to file " + myFile); }catch(IOException e){ // Handled exception } } ////// try { // CALLING THE PYTHON SCRIPT IN CHARGE OF UPLOADING THE JSON OBJECT'S INFO TO VIRTUOSO'S DB String target = new String("python3 curexRDF/main_json2rdf.py http://" + initializeService.getServerIP() + ":8890/sparql-auth"); Runtime rt = Runtime.getRuntime(); Process proc = rt.exec(target); int exitCode = proc.waitFor(); } catch (Throwable t) { t.printStackTrace(); } ////// } // End of initial for } // End of method public List getSnapshot(String snapshotId) { List allScans = scanInfoRepository.findAllBySnapshotId(snapshotId); allScans.forEach(scanInfo -> { List hosts = hostRepository.findAllByVlanNameAndSnapshotId(scanInfo.getVlanName(), snapshotId); List hostDtos = new ArrayList<>(); for (int i = 0; i < hosts.size(); i++) { HostDto hostDto = HostDto.createHostDto(hosts.get(i)); hostDtos.add(hostDto); List ports = portRepository.findAllByIpAndVlanNameAndSnapshotId(hostDto.getIp(), hostDto.getVlanName(), snapshotId); List portDtos = new ArrayList<>(); for (int j = 0; j < ports.size(); j++) { PortDto portDto = PortDto.createPortDto(ports.get(j)); portDtos.add(portDto); } hostDto.setPorts(portDtos); } scanInfo.setHost(hostDtos); }); return allScans; } public SnapshotChange evaluateChanges(List current, Date timestampSnapshot, String discoveryMethod){ List vlanChangeList = new ArrayList<>(); for(int i=0; i < current.size(); i++) { Snapshot previousOccurrence = snapshotRepository.findTopByVlanNameOrderByTimestampDistNodeEndDesc(current.get(i).getVlanName()); log.info("Previous occurrence detected:\n{}\n", previousOccurrence); if (previousOccurrence == null) { log.info("There was no previous information of a snapshot from \"{}\" vlan.", current.get(i).getVlanName()); // TODO: Everything is new, send as so (return =/= null). for (ScanInfoDto currentElem : current) { List deviceChangeList = new ArrayList<>(); List currentHosts = currentElem.getHost(); for (int x = 0; x < currentHosts.size(); x++) { HostDto currentHost = currentHosts.get(x); String type_of_change = "new"; // final object param Date timestampDevice = currentHost.getTimestamp_end(); // final object param String ip_address = currentHost.getIp(); // final object param String mac_address = currentHost.getMac(); // final object param String operating_system = currentHost.getOperatingSystem(); // final object param List portChangeList = new ArrayList<>(); List currentPorts = currentHost.getPorts(); for (int j = 0; j < currentPorts.size(); j++) { PortDto currentPort = currentPorts.get(j); String port = currentPort.getPortNumber(); // final object param String protocol = currentPort.getProtocol(); // final object param String service = currentPort.getServiceRunning(); // final object param String service_version = currentPort.getServiceVersion(); // final object param String status = currentPort.getState(); // final object param PortChange portToAdd = PortChange.createPortChange(port, protocol, service, service_version, status); portChangeList.add(portToAdd); } DeviceChange deviceToAdd = DeviceChange.createDeviceChange(timestampDevice, type_of_change, ip_address, mac_address, operating_system, portChangeList); deviceChangeList.add(deviceToAdd); } VlanChange vlanToAdd = VlanChange.createVlanChange(currentElem.getVlanName(), deviceChangeList); vlanChangeList.add(vlanToAdd); } return SnapshotChange.createSnapshotChange(timestampSnapshot, vlanChangeList, discoveryMethod); }else { // If there is a previous snapshot -> evaluate changes List previous = getSnapshot(previousOccurrence.getSnapshotId()); evaluateVlanFromScanInfo(current, vlanChangeList, previous); } } // end of initial for loop SnapshotChange changeSnapshot = SnapshotChange.createSnapshotChange(timestampSnapshot, vlanChangeList, discoveryMethod); log.info("Snapshot-Change item generated:\n{}\n", changeSnapshot); if(vlanChangeList.size() != 0) { return changeSnapshot; } return null; } public void evaluateVlanFromScanInfo(List current, List vlanChangeList, List previous){ for (ScanInfoDto currentElem : current) { List deviceChangeList = new ArrayList<>(); boolean vlanCoincidence = false; String vlan_id = currentElem.getVlanName(); // final object param for (ScanInfo previousElem : previous) { if (currentElem.getVlanName().equals(previousElem.getVlanName())) { // Dealing with an already scanned vlan. Validate its content. vlanCoincidence = true; log.info("[--CHANGE EVALUATION--] A vlan coincidence was found between {} and {}", currentElem.getVlanName(), previousElem.getVlanName()); ////////////////// evaluateHostFromVlan(currentElem.getHost(), deviceChangeList, previousElem.getHost()); ////////////////// break; } } if (vlanCoincidence == false) { // If no coincidence has been found for this element, it is a new undetected one. Register it as so. List currentHosts = currentElem.getHost(); for(int i=0; i portChangeList = new ArrayList<>(); List currentPorts = currentHost.getPorts(); for(int j=0; j 0) { // It is only necessary to store it if there are detected changes in its hosts. VlanChange vlanToAdd = VlanChange.createVlanChange(vlan_id, deviceChangeList); vlanChangeList.add(vlanToAdd); } else { log.info("[--CHANGE EVALUATION--] No changes in the assessed vlans."); } } } } public void evaluateHostFromVlan(List currentHosts, List deviceChangeList, List previousElem){ for (HostDto currentHost : currentHosts) { List portChangeList = new ArrayList<>(); boolean hostCoincidence = false; String type_of_change = ""; // final object param Date timestampDevice = currentHost.getTimestamp_end(); // final object param /*String ip_address = "no_change"; // final object param String mac_address = "no_change"; // final object param*/ String ip_address = currentHost.getIp(); // final object param String mac_address = currentHost.getMac(); String operating_system = "no_change"; // final object param for (HostDto previousHost : previousElem) { /* Need to verify these cases: (A) IP has changed - MAC has not (B) IP has not changed - MAC has */ if (currentHost.getIp().equals(previousHost.getIp())) { log.info("[--CHANGE EVALUATION--] A host coincidence has been found for {}.", currentHost.getIp()); hostCoincidence = true; if ((currentHost.getMac() == null && previousHost.getMac() == null) || (!(currentHost.getMac() == null ^ previousHost.getMac() == null) && (currentHost.getMac().equals(previousHost.getMac())))) { // Case (0 0) - none has changed + nothing to do } else { // Case (B) - (0 1) log.info("[--CHANGE EVALUATION--] The MAC address has changed: {} VS {}", currentHost.getMac(), previousHost.getMac()); mac_address = currentHost.getMac(); type_of_change = "modified"; } } else { ip_address = currentHost.getIp(); if ((currentHost.getMac() == null && previousHost.getMac() == null) || (!(currentHost.getMac() == null ^ previousHost.getMac() == null) && (currentHost.getMac().equals(previousHost.getMac())))) { // Case (A) - (1 0) log.info("[--CHANGE EVALUATION--] The IP has changed: {} VS {}", currentHost.getIp(), previousHost.getIp()); type_of_change = "modified"; hostCoincidence = true; } } if (hostCoincidence == true) { if ((currentHost.getOperatingSystem() == null && previousHost.getOperatingSystem() == null) || (!(currentHost.getOperatingSystem() == null ^ previousHost.getOperatingSystem() == null) && (currentHost.getOperatingSystem().equals(previousHost.getOperatingSystem())))) { log.info("[--CHANGE EVALUATION--] The operating system has not changed: {}", currentHost.getOperatingSystem()); } else { log.info("[--CHANGE EVALUATION--] The operating system has changed: {} VS {}", currentHost.getOperatingSystem(), previousHost.getOperatingSystem()); operating_system = currentHost.getOperatingSystem(); type_of_change = "modified"; } ////////////////// evaluatePortsFromHost(currentHost.getPorts(), portChangeList, previousHost.getPorts()); ////////////////// break; } } // I MAY INSERT PORTLIST INTO HOST HERE if (hostCoincidence == false) { // If no coincidence has been found for this element, it is a new undetected one. Register it as so. type_of_change = "new"; // final object param timestampDevice = currentHost.getTimestamp_end(); // final object param ip_address = currentHost.getIp(); // final object param mac_address = currentHost.getMac(); // final object param operating_system = currentHost.getOperatingSystem(); // final object param List currentPorts = currentHost.getPorts(); for(int j=0; j 0) { DeviceChange deviceToAdd = DeviceChange.createDeviceChange(timestampDevice, type_of_change, ip_address, mac_address, operating_system, portChangeList); deviceChangeList.add(deviceToAdd); } else { log.info("[--CHANGE EVALUATION--] No changes in the assessed hosts."); } } } } public void evaluatePortsFromHost(List currentPorts, List portChangeList, List previousPorts){ for (PortDto currentPort : currentPorts) { boolean portCoincidence = false; boolean portChange = false; String port = "no_change"; // final object param String protocol = "no_change"; // final object param String service = "no_change"; // final object param String service_version = "no_change"; // final object param String status = "no_change"; // final object param for (PortDto previousPort : previousPorts) { if (currentPort.getPortNumber().equals(previousPort.getPortNumber())) { portCoincidence = true; log.info("[--CHANGE EVALUATION--] Port {} coincidence detected.", currentPort.getPortNumber()); if (!currentPort.getProtocol().equals(previousPort.getProtocol())) { log.info("[--CHANGE EVALUATION--] Port protocol changed: {} VS {}", currentPort.getProtocol(), previousPort.getProtocol()); protocol = currentPort.getProtocol(); portChange = true; } if (!(currentPort.getServiceRunning() == null && previousPort.getServiceRunning() == null)) { if ((currentPort.getServiceRunning() == null ^ previousPort.getServiceRunning() == null) || (!currentPort.getServiceRunning().equals(previousPort.getServiceRunning()))) { log.info("[--CHANGE EVALUATION--] Port service changed: {} VS {}", currentPort.getServiceRunning(), previousPort.getServiceRunning()); service = currentPort.getServiceRunning(); portChange = true; } } if (!(currentPort.getServiceVersion() == null && previousPort.getServiceVersion() == null)) { if ((currentPort.getServiceVersion() == null ^ previousPort.getServiceVersion() == null) || (!currentPort.getServiceVersion().equals(previousPort.getServiceVersion()))) { log.info("[--CHANGE EVALUATION--] Port running service changed: {} VS {}", currentPort.getServiceVersion(), previousPort.getServiceVersion()); service_version = currentPort.getServiceVersion(); portChange = true; } } if (!currentPort.getState().equals(previousPort.getState())) { log.info("[--CHANGE EVALUATION--] Port status changed: {} VS {}", currentPort.getState(), previousPort.getState()); status = currentPort.getState(); portChange = true; } break; // break out of previous port loop } } if (portCoincidence == false) { // If no coincidence has been found for this element, it is a new undetected one. Register it as so. port = currentPort.getPortNumber(); // final object param protocol = currentPort.getProtocol(); // final object param service = currentPort.getServiceRunning(); // final object param service_version = currentPort.getServiceVersion(); // final object param status = currentPort.getState(); // final object param PortChange portToAdd = PortChange.createPortChange(port, protocol, service, service_version, status); portChangeList.add(portToAdd); } else { if (portChange == true) { PortChange portToAdd = PortChange.createPortChange(port, protocol, service, service_version, status); portChangeList.add(portToAdd); } else { log.info("[--CHANGE EVALUATION--] No changes in the assessed ports."); } } } } } // END OF SERVICE-CLASS