Package com.denimgroup.threadfix.service

Source Code of com.denimgroup.threadfix.service.DefectServiceImpl

////////////////////////////////////////////////////////////////////////
//
//     Copyright (c) 2009-2014 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 com.denimgroup.threadfix.data.dao.DefectDao;
import com.denimgroup.threadfix.data.dao.VulnerabilityDao;
import com.denimgroup.threadfix.data.entities.Application;
import com.denimgroup.threadfix.data.entities.Defect;
import com.denimgroup.threadfix.data.entities.Finding;
import com.denimgroup.threadfix.data.entities.Vulnerability;
import com.denimgroup.threadfix.logging.SanitizedLogger;
import com.denimgroup.threadfix.service.defects.AbstractDefectTracker;
import com.denimgroup.threadfix.service.defects.DefectMetadata;
import com.denimgroup.threadfix.service.defects.DefectTrackerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.denimgroup.threadfix.CollectionUtils.list;

@Service
@Transactional(readOnly = false)
public class DefectServiceImpl implements DefectService {

  private DefectDao defectDao = null;
  private VulnerabilityDao vulnerabilityDao = null;
  private ApplicationService applicationService = null;

  private final SanitizedLogger log = new SanitizedLogger(DefectService.class);
 
  @Autowired
  public DefectServiceImpl(DefectDao defectDao,
      VulnerabilityDao vulnerabilityDao,
      ApplicationService applicationService) {
    this.defectDao = defectDao;
    this.vulnerabilityDao = vulnerabilityDao;
    this.applicationService = applicationService;
  }

  @Override
  public List<Defect> loadAll() {
    return defectDao.retrieveAll();
  }

  @Override
  public Defect loadDefect(int defectId) {
    return defectDao.retrieveById(defectId);
  }

  @Override
  public Defect loadDefect(String nativeId) {
    return defectDao.retrieveByNativeId(nativeId);
  }

  @Override
  @Transactional(readOnly = false)
  public void storeDefect(Defect defect) {
    defectDao.saveOrUpdate(defect);
  }

    private String getAdditionalScannerInfo(List<Vulnerability> allVulns) {

        for (Vulnerability vuln : allVulns) {
            for (Finding finding: vuln.getFindings()){
                String scannerDetail = finding.getScannerDetail();
                if(scannerDetail != null && !scannerDetail.equals("")){
                    return scannerDetail;
                }
            }
        }

        return "";
    }

  @Override
  @Transactional(readOnly = false)
  public Map<String, Object> createDefect(List<Vulnerability> allVulns,
            String summary, String preamble, String component, String version,
      String severity, String priority, String status, Map<String,
            Object> fieldsMap, Boolean additionalScannerInfo) {
    if (allVulns == null || allVulns.size() == 0 || allVulns.get(0) == null ||
        allVulns.get(0).getApplication() == null) {
      log.warn("Null input, exiting.");
      return null;
    }

        Map<String, Object> map = new HashMap<>();
    Vulnerability vuln = allVulns.get(0);

    Application application = vuln.getApplication();
   
    if (application != null) {
      applicationService.decryptCredentials(application);
    }
   
    AbstractDefectTracker dt = DefectTrackerFactory.getTracker(application);
    if (dt == null) {
      log.warn("Unable to load Defect Tracker.");
      return null;
    }
   
    String editedSummary = summary, editedPreamble = preamble;

    // TODO handle error cases better.
    if (editedSummary == null || editedSummary.equals("")) {
      if (vuln.getGenericVulnerability() != null && vuln.getSurfaceLocation() != null) {
        editedSummary = createMessage(vuln);
      } else {
        editedSummary = "No editedSummary could be parsed.";
      }
    }

    if (editedPreamble == null || editedPreamble.equals("")) {
      if (vuln.getGenericVulnerability() != null && vuln.getSurfaceLocation() != null) {

                if(additionalScannerInfo){
                    String additionalScannerInfoStr = getAdditionalScannerInfo(allVulns);

                    if(additionalScannerInfoStr == null || additionalScannerInfoStr.equals("")){
                        editedPreamble = createMessage(vuln);
                    } else  {
                        editedPreamble = createMessageWithScannerInfo(vuln, additionalScannerInfoStr);
                    }
                } else {
                    editedPreamble = createMessage(vuln);
                }
      } else {
        editedPreamble = "No editedPreamble could be parsed.";
      }
    }

    List<Vulnerability> vulnsWithoutDefects = list();

    for (Vulnerability vulnerability : allVulns) {
      if (vulnerability.getDefect() == null) {
        vulnsWithoutDefects.add(vulnerability);
      }
    }

    if (vulnsWithoutDefects.size() == 0) {
      log.warn("All the vulnerabilities already had defects, exiting.");
      return null;
    }
   
    String defectTrackerName = null;
    if (application != null && application.getDefectTracker() != null
        && application.getDefectTracker().getDefectTrackerType() != null
        && application.getDefectTracker().getDefectTrackerType().getName() != null) {
      defectTrackerName = application.getDefectTracker().getDefectTrackerType().getName();
    }
   
    if (defectTrackerName != null) {
      log.info("About to submit a defect to " + defectTrackerName + ".");
    } else {
      log.info("About to submit a defect to the defect tracker.");
    }
   
    String defectId = dt.createDefect(vulnsWithoutDefects,
        new DefectMetadata(editedSummary, editedPreamble,
        component, version, severity, priority, status, fieldsMap));

    if (defectId != null) {
     
      Defect defect = new Defect();
      defect.setNativeId(defectId);
      defect.setVulnerabilities(vulnsWithoutDefects);
      defect.setApplication(application);
            Object sObj = null;
            if (fieldsMap != null && status == null) {
                sObj = fieldsMap.get("status")==null ? fieldsMap.get("Status") : fieldsMap.get("status");
            }
      status = (sObj != null ? String.valueOf(sObj) : status);

            // By default, set status to Open
            if (status == null)
                status = "Open";

            defect.setStatus(status);
      defect.setDefectURL(dt.getBugURL(
          application.getDefectTracker().getUrl(), defectId));
      defectDao.saveOrUpdate(defect);

      for (Vulnerability vulnerability : vulnsWithoutDefects) {
        vulnerability.setDefect(defect);
        vulnerability.setDefectSubmittedTime(Calendar.getInstance());
        vulnerabilityDao.saveOrUpdate(vulnerability);
      }
     
      if (defectTrackerName != null) {
        log.info("Successfully submitted defect to " + defectTrackerName + ".");
      } else {
        log.info("Successfully submitted defect.");
      }
            map.put(DEFECT, defect);
      return map;
    }
   
    if (defectTrackerName != null) {
      log.warn("There was an error submitting the defect to " + defectTrackerName + ".");
    } else {
      log.warn("There was an error submitting the defect.");
    }
        map.put(ERROR, dt.getLastError());
    return map;
  }

    private String createMessageWithScannerInfo(Vulnerability vuln, String scannerInfo) {

        String message = scannerInfo;

        if (vuln.getGenericVulnerability() != null && vuln.getSurfaceLocation() != null) {
            message += "\n" + vuln.getGenericVulnerability().getName() + " at "
                    + vuln.getSurfaceLocation().getPath();
        }

        return message;
    }

  private String createMessage(Vulnerability vuln) {
    if (vuln.getGenericVulnerability() != null && vuln.getSurfaceLocation() != null) {
      return vuln.getGenericVulnerability().getName() + " at "
          + vuln.getSurfaceLocation().getPath();
    } else {
      return "";
    }
  }

  // TODO make these error messages better
  @Override
  public String getErrorMessage(List<Vulnerability> vulns) {
    String noVulnsError = "No vulnerabilities were passed.";
    String noDefectTrackerError = "No defect tracker could be found - " +
        "check to see that you have entered your information.";
    String allVulnsAlreadyInSystem = "All the vulnerabilities were already in the system.";
    String defaultTrackerError = "There was an error connecting with the tracking system.";

    if (vulns == null || vulns.size() == 0) {
      return noVulnsError;
    }

    Vulnerability vuln = vulns.get(0);
    if (vuln == null || vuln.getApplication() == null) {
      return noDefectTrackerError;
    }

    Application application = vuln.getApplication();

        applicationService.decryptCredentials(application);

        AbstractDefectTracker dt = DefectTrackerFactory.getTracker(application);
    if (dt == null) {
      return noDefectTrackerError;
    }

    List<Vulnerability> vulnList = list();
   
    for (Vulnerability vulnerability : vulns) {
      if (vulnerability.getDefect() == null) {
        vulnList.add(vulnerability);
      }
    }

    if (vulnList.size() == 0) {
      return allVulnsAlreadyInSystem;
    }

    String trackerError = dt.getTrackerError();

    if (trackerError == null || trackerError.trim().equals("")) {
      return defaultTrackerError;
    } else {
      return trackerError;
    }
  }

  @Override
  @Transactional(readOnly = false)
  public boolean updateVulnsFromDefectTracker(Integer appId) {
   
    Application application = applicationService.loadApplication(appId);
   
    int numUpdated = 0;
   
    if (application == null) {
      log.warn("Application wasn't found, exiting.");
      return false;
    }
   
        applicationService.decryptCredentials(application);

    AbstractDefectTracker dt = DefectTrackerFactory.getTracker(application);
    if (dt == null) {
      log.warn("Unable to load Defect Tracker, exiting.");
      return false;
    }
   
    if (application.getDefectList() == null ||
        application.getDefectList().size() == 0) {
      log.warn("No Defects found, updating information is " +
          "only useful after creating Defects. Exiting.");
      return false;
    }

    Map<Defect, Boolean> defectMap = dt.getMultipleDefectStatus(
        application.getDefectList());
    if (defectMap == null) {
      log.warn("There was an error retrieving information from the " +
          "Defect Tracker, exiting.");
      return false;
    }

    log.info("About to update vulnerability information from the defect tracker.");
   
    for (Defect defect : defectMap.keySet()) {
      if (defect != null && defect.getVulnerabilities() != null
          && defectMap.containsKey(defect)) {
        for (Vulnerability vuln : defect.getVulnerabilities()) {
          Boolean defectOpenStatus = defectMap.get(defect);

          if (vuln.isActive() && defectOpenStatus != null &&
              !defectOpenStatus) {
            if (vuln.getDefectClosedTime() == null) {
              vuln.setDefectClosedTime(Calendar.getInstance());
              vulnerabilityDao.saveOrUpdate(vuln);
              numUpdated += 1;
            }
          }
        }
      }
    }
   
    if (numUpdated == 0) {
      log.info("No vulnerabilities were updated. " +
          "This could just mean that no issues were closed.");
    } else {
      log.info("Updated information for " + numUpdated + " vulnerabilities.");
    }
   
    return true;
  }

  @Override
  public void deleteByDefectTrackerId(Integer defectTrackerId) {
    log.info("Deleting Defects connected to the Defect Tracker with the ID " + defectTrackerId);
    defectDao.deleteByDefectTrackerId(defectTrackerId);
  }

  @Override
  public void deleteByApplicationId(Integer applicationId) {
    log.info("Deleting Defects connected to the Application with the ID " + applicationId);
    defectDao.deleteByApplicationId(applicationId);
  }

  @Override
  public boolean mergeDefect(List<Vulnerability> vulnerabilities, String id) {
   
    if (vulnerabilities == null || vulnerabilities.size() == 0 || vulnerabilities.get(0) == null ||
        vulnerabilities.get(0).getApplication() == null) {
      log.warn("Null input, exiting.");
      return false;
    }
   
    Vulnerability vuln = vulnerabilities.get(0);

    Application application = vuln.getApplication();

        if (application == null) {
            return false;
        }

        applicationService.decryptCredentials(application);

    AbstractDefectTracker dt = DefectTrackerFactory.getTracker(application);
    if (dt == null) {
      log.warn("Unable to load Defect Tracker.");
      return false;
    }
    Defect defect = new Defect();
    defect.setNativeId(id);
    defect.setDefectURL(dt.getBugURL(
        application.getDefectTracker().getUrl(), id));
    defect.setApplication(application);
    List<Defect> defectList = list();
    defectList.add(defect);
        Map<Defect, Boolean> map = dt.getMultipleDefectStatus(defectList);
        if (map.isEmpty())
            return false;
    defectDao.saveOrUpdate(defect);

    for (Vulnerability vulnerability : vulnerabilities) {
      vulnerability.setDefect(defect);
      vulnerability.setDefectSubmittedTime(Calendar.getInstance());
      vulnerabilityDao.saveOrUpdate(vulnerability);
    }

    log.info("Successfully merged vulns to Defect ID" + id + ".");

    return true;
  }
}
TOP

Related Classes of com.denimgroup.threadfix.service.DefectServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.