Java tutorial
/* * This file is part of Dependency-Track. * * Dependency-Track is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Dependency-Track is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * Dependency-Track. If not, see http://www.gnu.org/licenses/. */ package org.owasp.dependencytrack.dao; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.criterion.ProjectionList; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.owasp.dependencytrack.model.Application; import org.owasp.dependencytrack.model.ApplicationDependency; import org.owasp.dependencytrack.model.ApplicationVersion; import org.owasp.dependencytrack.model.LibraryVersion; import org.owasp.dependencytrack.model.ScanResult; import org.owasp.dependencytrack.model.Vulnerability; import org.owasp.dependencytrack.model.VulnerabilitySummary; import org.owasp.dependencytrack.model.VulnerabilityTrend; import org.owasp.dependencytrack.model.VulnerableComponent; import org.owasp.dependencytrack.tasks.DependencyCheckAnalysisRequestEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @Repository("vulnerabilityDao") @SuppressWarnings("unchecked") public class VulnerabilityDaoImpl extends BaseDao implements VulnerabilityDao { /** * Setup logger */ private static final Logger LOGGER = LoggerFactory.getLogger(VulnerabilityDaoImpl.class); /** * Event publisher */ private ApplicationEventPublisher eventPublisher; /** * Returns a list of Vulnerability objects for LibraryVersions that have a * dependency of the specified ApplicationVersion. * * @param applicationVersion * The ApplicationVersion to retrieve vulnerability for * @return a List of Vulnerability objects */ @SuppressWarnings("unchecked") public List<VulnerableComponent> getVulnerableComponents(final ApplicationVersion applicationVersion) { final Session session = getSession(); final List<VulnerableComponent> vulnerableComponents = new ArrayList<>(); // Retrieve all of the library versions from the specified application version final List<LibraryVersion> libvers = new ArrayList<>(); final Query query = session.createQuery("from ApplicationDependency where applicationVersion=:version"); query.setParameter("version", applicationVersion); final List<ApplicationDependency> deps = query.list(); for (ApplicationDependency dep : deps) { libvers.add(dep.getLibraryVersion()); } // Iterate through the library versions looking for scan results for (LibraryVersion libraryVersion : libvers) { final Criteria criteria = session.createCriteria(ScanResult.class); criteria.add(Restrictions.eq("libraryVersion", libraryVersion)); final ProjectionList projList = Projections.projectionList(); projList.add(Projections.property("libraryVersion")); projList.add(Projections.property("vulnerability")); criteria.setProjection(Projections.distinct(projList)); final List<Object[]> results = criteria.list(); final List<Vulnerability> vulns = new ArrayList<>(); for (Object[] result : results) { for (Object object : result) { if (object instanceof Vulnerability) { vulns.add((Vulnerability) object); } } } final VulnerableComponent vulnerableComponent = new VulnerableComponent(); vulnerableComponent.setLibraryVersion(libraryVersion); vulnerableComponent.setVulnerabilities(vulns); // Add the VulnerableComponent to the list of vulnerableComponents to return vulnerableComponents.add(vulnerableComponent); } return vulnerableComponents; } public List<VulnerabilitySummary> getVulnerabilitySummary(final int id) { final Session session = getSession(); final List<VulnerabilitySummary> summaryList = new ArrayList<>(); final Query query = session.createQuery("from Application where id=:id"); query.setParameter("id", id); final List<Application> applications = query.list(); for (Application application : applications) { for (ApplicationVersion version : application.getVersions()) { summaryList.add(getVulnerabilitySummary(version)); } } return summaryList; } public VulnerabilitySummary getVulnerabilitySummary(final ApplicationVersion applicationVersion) { final Session session = getSession(); final List<VulnerableComponent> vulnerableComponents = getVulnerableComponents(applicationVersion); final VulnerabilitySummary vulnerabilitySummary = new VulnerabilitySummary(); vulnerabilitySummary.setApplicationVersion(applicationVersion); vulnerabilitySummary.setVulnerableComponents(vulnerableComponents.size()); for (VulnerableComponent vulnerableComponent : vulnerableComponents) { final List<Vulnerability> vulnerabilities = vulnerableComponent.getVulnerabilities(); for (Vulnerability vulnerability : vulnerabilities) { if (vulnerability.getSeverity() == Vulnerability.Severity.HIGH) { vulnerabilitySummary.setHigh(vulnerabilitySummary.getHigh() + 1); } else if (vulnerability.getSeverity() == Vulnerability.Severity.MEDIUM) { vulnerabilitySummary.setMedium(vulnerabilitySummary.getMedium() + 1); } else if (vulnerability.getSeverity() == Vulnerability.Severity.LOW) { vulnerabilitySummary.setLow(vulnerabilitySummary.getLow() + 1); } } } return vulnerabilitySummary; } public List<Vulnerability> getVulnsForLibraryVersion(final LibraryVersion libraryVersion) { final Session session = getSession(); final Criteria criteria = session.createCriteria(ScanResult.class); criteria.add(Restrictions.eq("libraryVersion", libraryVersion)); final ProjectionList projList = Projections.projectionList(); projList.add(Projections.property("libraryVersion")); projList.add(Projections.property("vulnerability")); criteria.setProjection(Projections.distinct(projList)); final List<Object[]> results = criteria.list(); final List<Vulnerability> vulns = new ArrayList<>(); for (Object[] result : results) { for (Object object : result) { if (object instanceof Vulnerability) { vulns.add((Vulnerability) object); } } } return vulns; } /** * Performs a series of queries to obtain scan result history for the * specified timespan and constructs a VulnerabilityTrend object with * historical vulnerability data. * * @param timespan * the timespan to perform the query on (i.e. last 30, 60, 90, * 365 days) * @param appVersionId * todo future use * @return a VulnerabilityTrend object containing historical data */ public VulnerabilityTrend getVulnerabilityTrend(final VulnerabilityTrend.Timespan timespan, int appVersionId) { final Session session = getSession(); final Map<Date, VulnerabilitySummary> map = new LinkedHashMap<>(); // Get the start date and end date for retrieving result info final Calendar startDate = Calendar.getInstance(); final Calendar endDate = Calendar.getInstance(); startDate.add(Calendar.DAY_OF_MONTH, -timespan.getDays()); // Using the date range above, check to see how many datapoints are in that range final Query dateQuery = session.createQuery( "select distinct s.scanDate from ScanResult s where s.scanDate >= ? and s.scanDate <= ? order by s.scanDate asc"); dateQuery.setParameter(0, startDate.getTime()); dateQuery.setParameter(1, endDate.getTime()); final List<Date> dates = dateQuery.list(); final int numDates = dates.size(); final List<Date> dataPointDates = new ArrayList<>(); if (numDates < timespan.getDivisions()) { dataPointDates.addAll(dates); } else { final int dataPoints = timespan.getDivisions(); final double sliceEvery = ((double) dates.size() / (double) dataPoints); int sliceEveryProgress = 0; for (int i = 0; i < dataPoints; i++) { if (i == 0) { // Always include the first date from the results dataPointDates.add(dates.get(0)); } else if (i == (dataPoints - 1)) { // Always include the last date from the results dataPointDates.add(dates.get(dates.size() - 1)); } else if (sliceEveryProgress >= i) { // Include everything in between dataPointDates.add(dates.get(i)); } sliceEveryProgress += sliceEvery; } } // Iterate for the number of datapoints we're going to eventually present for (Date dataPointDate : dataPointDates) { final Query query = session.createQuery("select distinct s from ScanResult s where s.scanDate = ?"); query.setParameter(0, dataPointDate); final List<ScanResult> scanResults = query.list(); for (ScanResult scanResult : scanResults) { addVulnerabilityToTrend(map, scanResult); } } final VulnerabilityTrend trend = new VulnerabilityTrend(); final Set<Date> keys = map.keySet(); for (Date date : keys) { trend.addData(date, map.get(date)); } return trend; } /** * Adds the specified scan result to a growing map * * @param map * a map of VulnerabilitySummary object using Date as the key * @param scanResult * a ScanResult object */ private void addVulnerabilityToTrend(Map<Date, VulnerabilitySummary> map, ScanResult scanResult) { final Date scanDate = scanResult.getScanDate(); final Vulnerability vulnerability = scanResult.getVulnerability(); VulnerabilitySummary summary = map.get(scanDate); if (summary == null) { summary = new VulnerabilitySummary(); map.put(scanDate, summary); } final Vulnerability.Severity severity = vulnerability.getSeverity(); if (Vulnerability.Severity.HIGH == severity) { summary.addHigh(); } else if (Vulnerability.Severity.MEDIUM == severity) { summary.addMedium(); } else if (Vulnerability.Severity.LOW == severity) { summary.addLow(); } } public void initiateFullDependencyCheckScan() { final Session session = getSession(); final Query query = session.createQuery("from LibraryVersion"); final List<LibraryVersion> libraryVersions = query.list(); eventPublisher.publishEvent(new DependencyCheckAnalysisRequestEvent(this, libraryVersions)); } public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } /** * Update the vulnerability count in all ApplicationVersion objects. */ @Transactional(rollbackFor = Exception.class) public void updateApplicationVersionVulnerabilityCount() { final Session session = getSession(); final Query appVerQuery = session.createQuery("FROM ApplicationVersion "); final List<ApplicationVersion> applicationVersions = appVerQuery.list(); for (ApplicationVersion applicationVersion : applicationVersions) { final Query depQuery = session .createQuery("from ApplicationDependency where applicationVersion=:version"); depQuery.setParameter("version", applicationVersion); int appVulnCount = 0; final List<ApplicationDependency> dependencies = depQuery.list(); for (ApplicationDependency dependency : dependencies) { final LibraryVersion libraryVersion = dependency.getLibraryVersion(); appVulnCount += libraryVersion.getVulnCount(); } applicationVersion.setVulnCount(appVulnCount); session.save(applicationVersion); } } /** * Update the vulnerability count in all LibraryVersion objects. */ @Transactional(rollbackFor = Exception.class) public void updateLibraryVersionVulnerabilityCount() { final Session session = getSession(); final Query libverQuery = session.createQuery("FROM LibraryVersion"); final List<LibraryVersion> libraryVersions = libverQuery.list(); for (LibraryVersion libraryVersion : libraryVersions) { final SQLQuery vulnQuery = session.createSQLQuery( "SELECT DISTINCT vulnerabilityid FROM scanresult WHERE libraryversionid=:libraryVersion"); vulnQuery.setParameter("libraryVersion", libraryVersion.getId()); final int vulnCount = vulnQuery.list().size(); libraryVersion.setVulnCount(vulnCount); session.save(libraryVersion); } } }