//////////////////////////////////////////////////////////////////////// // // Copyright (c) 2009-2013 Denim Group, Ltd. // // The contents of this file are subject to the Mozilla Public License // Version 2.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.mozilla.org/MPL/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations // under the License. // // The Original Code is ThreadFix. // // The Initial Developer of the Original Code is Denim Group, Ltd. // Portions created by Denim Group, Ltd. are Copyright (C) // Denim Group, Ltd. All Rights Reserved. // // Contributor(s): Denim Group, Ltd. // //////////////////////////////////////////////////////////////////////// package com.denimgroup.threadfix.service; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.BindingResult; import com.denimgroup.threadfix.data.dao.ApplicationChannelDao; import com.denimgroup.threadfix.data.dao.ApplicationDao; import com.denimgroup.threadfix.data.dao.ChannelSeverityDao; import com.denimgroup.threadfix.data.dao.ChannelTypeDao; import com.denimgroup.threadfix.data.dao.ChannelVulnerabilityDao; import com.denimgroup.threadfix.data.dao.RemoteProviderApplicationDao; import com.denimgroup.threadfix.data.entities.Application; import com.denimgroup.threadfix.data.entities.ApplicationChannel; import com.denimgroup.threadfix.data.entities.ChannelType; import com.denimgroup.threadfix.data.entities.RemoteProviderApplication; import com.denimgroup.threadfix.data.entities.RemoteProviderType; import com.denimgroup.threadfix.data.entities.Scan; import com.denimgroup.threadfix.service.queue.QueueSender; import com.denimgroup.threadfix.service.remoteprovider.RemoteProviderFactory; @Service @Transactional(readOnly = false) public class RemoteProviderApplicationServiceImpl implements RemoteProviderApplicationService { private final SanitizedLogger log = new SanitizedLogger("RemoteProviderApplicationService"); private ChannelVulnerabilityDao channelVulnerabilityDao = null; private ChannelSeverityDao channelSeverityDao = null; private ChannelTypeDao channelTypeDao = null; private RemoteProviderApplicationDao remoteProviderApplicationDao = null; private ScanMergeService scanMergeService = null; private ApplicationDao applicationDao = null; private ApplicationChannelDao applicationChannelDao = null; private QueueSender queueSender = null; @Autowired public RemoteProviderApplicationServiceImpl(ChannelTypeDao channelTypeDao, ChannelVulnerabilityDao channelVulnerabilityDao, ChannelSeverityDao channelSeverityDao, RemoteProviderApplicationDao remoteProviderApplicationDao, ScanMergeService scanMergeService, ApplicationDao applicationDao, QueueSender queueSender, ApplicationChannelDao applicationChannelDao) { this.channelVulnerabilityDao = channelVulnerabilityDao; this.channelTypeDao = channelTypeDao; this.channelSeverityDao = channelSeverityDao; this.remoteProviderApplicationDao = remoteProviderApplicationDao; this.scanMergeService = scanMergeService; this.applicationDao = applicationDao; this.applicationChannelDao = applicationChannelDao; this.queueSender = queueSender; } @Override public RemoteProviderApplication load(int id) { return remoteProviderApplicationDao.retrieveById(id); } @Override public List<RemoteProviderApplication> loadAllWithTypeId(int id) { return remoteProviderApplicationDao.retrieveAllWithTypeId(id); } @Override public void store(RemoteProviderApplication remoteProviderApplication) { remoteProviderApplicationDao.saveOrUpdate(remoteProviderApplication); } @Override public void updateApplications(RemoteProviderType remoteProviderType) { List<RemoteProviderApplication> newApps = getRemoteProviderFactory() .fetchApplications(remoteProviderType); // We can't use remoteProviderType.getRemoteProviderApplications() // because the old session is closed List<RemoteProviderApplication> appsForType = loadAllWithTypeId( remoteProviderType.getId()); if (newApps == null || newApps.size() == 0) { return; } else { Set<String> appIds = new TreeSet<String>(); if (appsForType != null && appsForType.size() > 0) { for (RemoteProviderApplication app : appsForType) { if (app == null || app.getNativeId() == null) { continue; } if (app.getNativeId().length() >= RemoteProviderApplication.NATIVE_ID_LENGTH) { log.warn("A Remote Provider application came out of the database with more than " + RemoteProviderApplication.NATIVE_ID_LENGTH + " characters in it. This shouldn't be possible."); appIds.add(app.getNativeId().substring(0, RemoteProviderApplication.NATIVE_ID_LENGTH-1)); } else { appIds.add(app.getNativeId()); } } } for (RemoteProviderApplication app : newApps) { if (app != null && !appIds.contains(app.getNativeId())) { app.setRemoteProviderType(remoteProviderType); appsForType.add(app); remoteProviderType.setRemoteProviderApplications(appsForType); store(app); } } } } @Override public List<RemoteProviderApplication> getApplications( RemoteProviderType remoteProviderType) { if (remoteProviderType == null) { return null; } List<RemoteProviderApplication> newApps = getRemoteProviderFactory().fetchApplications(remoteProviderType); if (newApps == null || newApps.size() == 0) { return null; } if (newApps != null && newApps.size() > 1) { Collections.sort(newApps, new Comparator<RemoteProviderApplication>() { public int compare(RemoteProviderApplication f1, RemoteProviderApplication f2) { return f1.getNativeId().compareTo(f2.getNativeId()); } }); } for (RemoteProviderApplication app : newApps) { if (app == null) { continue; } if (app.getNativeId() != null && app.getNativeId().length() >= RemoteProviderApplication.NATIVE_ID_LENGTH) { log.warn("A Remote Provider application was parsed that has more than " + RemoteProviderApplication.NATIVE_ID_LENGTH + " characters in it. The name is being trimmed but this" + " should not prevent use of the application"); app.setNativeId(app.getNativeId().substring(0, RemoteProviderApplication.NATIVE_ID_LENGTH-1)); } app.setRemoteProviderType(remoteProviderType); } return newApps; } @Override public void deleteApps(RemoteProviderType remoteProviderType) { if (remoteProviderType != null && remoteProviderType .getRemoteProviderApplications() != null) { log.info("Deleting apps for Remote Provider type " + remoteProviderType.getName() + " (id=" + remoteProviderType.getId() + ")"); for (RemoteProviderApplication app : remoteProviderType .getRemoteProviderApplications()) { log.info("Deleting Remote Application " + app.getNativeId() + " (id = " + app.getId() + ", type id=" + remoteProviderType.getId() + ")"); remoteProviderApplicationDao.delete(app); } } } @Override @Transactional public boolean importScansForApplication( RemoteProviderApplication remoteProviderApplication) { if (remoteProviderApplication == null) return false; List<Scan> resultScans = getRemoteProviderFactory().fetchScans(remoteProviderApplication); boolean success = false; if (resultScans != null && resultScans.size() > 0) { Collections.sort(resultScans, new Comparator<Scan>() { public int compare(Scan scan1, Scan scan2){ Calendar scan1Time = scan1.getImportTime(); Calendar scan2Time = scan2.getImportTime(); if (scan1Time == null || scan2Time == null) return 0; return scan1Time.compareTo(scan2Time); } }); for (Scan resultScan : resultScans) { if (resultScan == null || resultScan.getFindings() == null || resultScan.getFindings().size() == 0) { log.warn("Remote Scan import returned a null scan or a scan with no findings."); } else if (remoteProviderApplication.getLastImportTime() != null && (resultScan.getImportTime() == null || !remoteProviderApplication.getLastImportTime().before( resultScan.getImportTime()))) { log.warn("Remote Scan was not newer than the last imported scan " + "for this RemoteProviderApplication."); } else { log.info("Scan was parsed and has findings, passing to ScanMergeService."); remoteProviderApplication.setLastImportTime(resultScan.getImportTime()); remoteProviderApplicationDao.saveOrUpdate(remoteProviderApplication); if (resultScan.getApplicationChannel() == null) { if (remoteProviderApplication.getApplicationChannel() != null) { resultScan.setApplicationChannel(remoteProviderApplication.getApplicationChannel()); } else { log.error("Didn't have enough application channel information."); success = false; } } if (resultScan.getApplicationChannel() != null) { if (resultScan.getApplicationChannel().getScanList() == null) { resultScan.getApplicationChannel().setScanList(new ArrayList<Scan>()); } if (!resultScan.getApplicationChannel().getScanList().contains(resultScan)) { resultScan.getApplicationChannel().getScanList().add(resultScan); } scanMergeService.processRemoteScan(resultScan); success = true; } } } } return success; } private RemoteProviderFactory getRemoteProviderFactory() { return new RemoteProviderFactory(channelTypeDao, channelVulnerabilityDao, channelSeverityDao); } @Override public void processApp(BindingResult result, RemoteProviderApplication remoteProviderApplication) { Application application = applicationDao.retrieveById( remoteProviderApplication.getApplication().getId()); if (application == null) { result.rejectValue("application.id", "errors.invalid", new String[] {"Application"},"Application choice was invalid."); return; } if (application.getRemoteProviderApplications() == null) { application.setRemoteProviderApplications( new ArrayList<RemoteProviderApplication>()); } if (!application.getRemoteProviderApplications().contains(remoteProviderApplication)) { application.getRemoteProviderApplications().add(remoteProviderApplication); remoteProviderApplication.setApplication(application); } ChannelType type = remoteProviderApplication.getRemoteProviderType().getChannelType(); if (application.getChannelList() == null || application.getChannelList().size() == 0) { application.setChannelList(new ArrayList<ApplicationChannel>()); } Integer previousId = null; if (remoteProviderApplication.getApplicationChannel() != null) { previousId = remoteProviderApplication.getApplicationChannel().getId(); } remoteProviderApplication.setApplicationChannel(null); for (ApplicationChannel applicationChannel : application.getChannelList()) { if (applicationChannel.getChannelType().getName().equals(type.getName())) { remoteProviderApplication.setApplicationChannel(applicationChannel); if (applicationChannel.getScanList() != null && applicationChannel.getScanList().size() > 0) { List<Scan> scans = applicationChannel.getScanList(); Collections.sort(scans,Scan.getTimeComparator()); remoteProviderApplication.setLastImportTime( scans.get(scans.size() - 1).getImportTime()); } else { remoteProviderApplication.setLastImportTime(null); } break; } } if (remoteProviderApplication.getApplicationChannel() == null) { ApplicationChannel channel = new ApplicationChannel(); channel.setApplication(application); if (remoteProviderApplication.getRemoteProviderType() != null && remoteProviderApplication.getRemoteProviderType().getChannelType() != null) { channel.setChannelType(remoteProviderApplication. getRemoteProviderType().getChannelType()); applicationChannelDao.saveOrUpdate(channel); } remoteProviderApplication.setLastImportTime(null); remoteProviderApplication.setApplicationChannel(channel); application.getChannelList().add(channel); } if (remoteProviderApplication.getApplicationChannel() == null || previousId == null || !previousId.equals(remoteProviderApplication .getApplicationChannel().getId())) { store(remoteProviderApplication); applicationDao.saveOrUpdate(application); } } @Override public List<RemoteProviderApplication> loadAllWithMappings() { return remoteProviderApplicationDao.retrieveAllWithMappings(); } @Override public void addBulkImportToQueue(RemoteProviderType remoteProviderType) { if (remoteProviderType == null || remoteProviderType.getRemoteProviderApplications() == null || remoteProviderType.getRemoteProviderApplications().isEmpty()) { log.error("Null remote provider type passed to addBulkImportToQueue. Something went wrong."); return; } if (remoteProviderType.getHasConfiguredApplications()) { log.info("At least one application is configured."); queueSender.addRemoteProviderImport(remoteProviderType); } else { log.error("No apps were configured with applications."); } } }