/** * Copyright (c) Codice Foundation * <p> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p> * This program 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 * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package ddf.lib; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.stream.Collectors; import org.apache.commons.io.IOUtils; import org.apache.maven.shared.invoker.DefaultInvocationRequest; import org.apache.maven.shared.invoker.DefaultInvoker; import org.apache.maven.shared.invoker.InvocationRequest; import org.apache.maven.shared.invoker.InvocationResult; import org.apache.maven.shared.invoker.Invoker; import org.apache.maven.shared.invoker.MavenInvocationException; import org.codehaus.plexus.util.StringUtils; public class OwaspDiffRunner { public static final String MAVEN_VERSION_COMMAND = "mvn -version"; public static final String MAVEN_SETTINGS_COMMAND = "mvn help:effective-settings"; public static final String GIT_DIFF_NAME_COMMAND = "git diff --name-only "; public static final String GIT_SHORT_BRANCH_NAME_COMMAND = "git rev-parse --abbrev-ref HEAD"; private static final String DASHES = StringUtils.repeat("-", 25); public static final String BEGIN_OWASP_AUDIT = DASHES + " BEGIN OWASP DIFF AUDIT " + DASHES; public static final String END_OWASP_AUDIT = DASHES + " END OWASP DIFF AUDIT " + DASHES; public static final String PROJECT_ROOT = System.getProperty("user.dir") .split("/libs/owasp-diff-runner")[0]; private static String mavenHome; private static String localRepo; private static Runtime runTime = Runtime.getRuntime(); private static Invoker invoker = new DefaultInvoker(); public OwaspDiffRunner(Runtime runTime, Invoker invoker) { this.runTime = runTime; this.invoker = invoker; } public static void main(String[] args) throws OwaspDiffRunnerException { System.out.println(BEGIN_OWASP_AUDIT); try { mavenHome = getMavenHome(); localRepo = getLocalRepo(); String modulesOfChangedPoms = getModulesOfChangedPoms(); if (modulesOfChangedPoms.isEmpty()) { System.out.println("No changed poms."); return; } InvocationRequest request = new DefaultInvocationRequest(); request.setPomFile(new File(PROJECT_ROOT + File.separator + "pom.xml")); request.setBaseDirectory(new File(PROJECT_ROOT)); request.setLocalRepositoryDirectory(new File(localRepo)); request.setGoals(Arrays.asList("dependency-check:check", "--quiet", "-pl", modulesOfChangedPoms, "-Powasp")); invoker.setMavenHome(new File(mavenHome)); System.out.println("-- Maven home: " + mavenHome); System.out.println("-- Local Maven repo: " + localRepo); InvocationResult mavenBuildResult; try { mavenBuildResult = invoker.execute(request); } catch (MavenInvocationException e) { throw new OwaspDiffRunnerException( OwaspDiffRunnerException.UNABLE_TO_RUN_MAVEN + modulesOfChangedPoms, e); } if (mavenBuildResult.getExitCode() != 0) { throw new OwaspDiffRunnerException(OwaspDiffRunnerException.FOUND_VULNERABILITIES); } } finally { System.out.println(END_OWASP_AUDIT); } } private static String getModulesOfChangedPoms() throws OwaspDiffRunnerException { String changedFiles; String currentBranchName; try { currentBranchName = IOUtils.toString(runTime.exec(GIT_SHORT_BRANCH_NAME_COMMAND) .getInputStream()) .replace(File.separator, "") .replace(System.getProperty("line.separator"), ""); changedFiles = IOUtils.toString(runTime.exec( GIT_DIFF_NAME_COMMAND + currentBranchName + "..master") .getInputStream()); } catch (IOException e) { throw new OwaspDiffRunnerException(OwaspDiffRunnerException.UNABLE_TO_RETRIEVE_GIT_INFO, e); } System.out.println( "Comparing commits of branch " + currentBranchName + " to master. Changed poms: "); return Arrays.stream(changedFiles.split(System.getProperty("line.separator"))) .filter(path -> path.endsWith("pom.xml")) .peek(System.out::println) .map(path -> path.endsWith(File.separator + "pom.xml") ? path.replace(File.separator + "pom.xml", "") : path.replace("pom.xml", File.separator)) //Special case for the root pom, change path pom.xml -> / .collect(Collectors.joining(",")); } private static String getMavenHome() throws OwaspDiffRunnerException { String mavenHome; String mavenVersionInfo; try { mavenVersionInfo = IOUtils.toString(runTime.exec(MAVEN_VERSION_COMMAND) .getInputStream()); //parsing console response, confirmed to work with at least maven version 3.3.9 mavenHome = Arrays.stream(mavenVersionInfo.split(System.getProperty("line.separator"))) .filter(str -> str.contains("Maven home:")) .findFirst() .get() .split("Maven home:")[1].trim(); } catch (Exception e) { throw new OwaspDiffRunnerException(OwaspDiffRunnerException.UNABLE_TO_RETRIEVE_MAVEN_HOME, e); } return mavenHome; } private static String getLocalRepo() throws OwaspDiffRunnerException { String mavenHelpInfo; String localRepoProperty = System.getProperty("maven.repo.local"); if (StringUtils.isNotEmpty(localRepoProperty)) { if (!new File(localRepoProperty).exists()) { throw new OwaspDiffRunnerException( OwaspDiffRunnerException.UNABLE_TO_RETRIEVE_LOCAL_MAVEN_REPO + localRepoProperty); } return localRepoProperty; } try { mavenHelpInfo = IOUtils.toString(runTime.exec(MAVEN_SETTINGS_COMMAND) .getInputStream()); //parsing console response, confirmed to work with at least maven version 3.3.9 return mavenHelpInfo.split("<localRepository(.*\")?>")[1].split("</localRepository>")[0]; } catch (Exception e) { throw new OwaspDiffRunnerException(OwaspDiffRunnerException.UNABLE_TO_RETRIEVE_LOCAL_MAVEN_REPO, e); } } }