View Javadoc
1   /*
2    * This file is part of dependency-check-cli.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck;
19  
20  import java.io.File;
21  import java.io.FileNotFoundException;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.List;
25  import java.util.logging.Level;
26  import java.util.logging.Logger;
27  import org.apache.commons.cli.ParseException;
28  import org.owasp.dependencycheck.cli.CliParser;
29  import org.owasp.dependencycheck.data.nvdcve.CveDB;
30  import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
31  import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
32  import org.owasp.dependencycheck.dependency.Dependency;
33  import org.owasp.dependencycheck.reporting.ReportGenerator;
34  import org.owasp.dependencycheck.utils.LogUtils;
35  import org.owasp.dependencycheck.utils.Settings;
36  
37  /**
38   * The command line interface for the DependencyCheck application.
39   *
40   * @author Jeremy Long <jeremy.long@owasp.org>
41   */
42  public class App {
43  
44      /**
45       * The location of the log properties configuration file.
46       */
47      private static final String LOG_PROPERTIES_FILE = "log.properties";
48  
49      /**
50       * The logger.
51       */
52      private static final Logger LOGGER = Logger.getLogger(App.class.getName());
53  
54      /**
55       * The main method for the application.
56       *
57       * @param args the command line arguments
58       */
59      public static void main(String[] args) {
60          final App app = new App();
61          app.run(args);
62      }
63  
64      /**
65       * Main CLI entry-point into the application.
66       *
67       * @param args the command line arguments
68       */
69      public void run(String[] args) {
70  
71          final CliParser cli = new CliParser();
72          try {
73              cli.parse(args);
74          } catch (FileNotFoundException ex) {
75              System.err.println(ex.getMessage());
76              cli.printHelp();
77              return;
78          } catch (ParseException ex) {
79              System.err.println(ex.getMessage());
80              cli.printHelp();
81              return;
82          }
83  
84          final InputStream in = App.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
85          LogUtils.prepareLogger(in, cli.getVerboseLog());
86  
87          if (cli.isGetVersion()) {
88              cli.printVersionInfo();
89          } else if (cli.isRunScan()) {
90              populateSettings(cli);
91              runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles());
92          } else {
93              cli.printHelp();
94          }
95      }
96  
97      /**
98       * Scans the specified directories and writes the dependency reports to the reportDirectory.
99       *
100      * @param reportDirectory the path to the directory where the reports will be written
101      * @param outputFormat the output format of the report
102      * @param applicationName the application name for the report
103      * @param files the files/directories to scan
104      */
105     private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files) {
106         Engine scanner = null;
107         try {
108             scanner = new Engine();
109 
110             for (String file : files) {
111                 scanner.scan(file);
112             }
113 
114             scanner.analyzeDependencies();
115             final List<Dependency> dependencies = scanner.getDependencies();
116             DatabaseProperties prop = null;
117             CveDB cve = null;
118             try {
119                 cve = new CveDB();
120                 cve.open();
121                 prop = cve.getDatabaseProperties();
122             } catch (DatabaseException ex) {
123                 LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
124             } finally {
125                 if (cve != null) {
126                     cve.close();
127                 }
128             }
129             final ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop);
130             try {
131                 report.generateReports(reportDirectory, outputFormat);
132             } catch (IOException ex) {
133                 LOGGER.log(Level.SEVERE, "There was an IO error while attempting to generate the report.");
134                 LOGGER.log(Level.FINE, null, ex);
135             } catch (Throwable ex) {
136                 LOGGER.log(Level.SEVERE, "There was an error while attempting to generate the report.");
137                 LOGGER.log(Level.FINE, null, ex);
138             }
139         } catch (DatabaseException ex) {
140             LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
141             LOGGER.log(Level.FINE, "", ex);
142         } finally {
143             Settings.cleanup();
144             if (scanner != null) {
145                 scanner.cleanup();
146             }
147         }
148     }
149 
150     /**
151      * Updates the global Settings.
152      *
153      * @param cli a reference to the CLI Parser that contains the command line arguments used to set the corresponding
154      * settings in the core engine.
155      */
156     private void populateSettings(CliParser cli) {
157 
158         Settings.initialize();
159 
160         final boolean autoUpdate = cli.isAutoUpdate();
161         final String connectionTimeout = cli.getConnectionTimeout();
162         final String proxyUrl = cli.getProxyUrl();
163         final String proxyPort = cli.getProxyPort();
164         final String proxyUser = cli.getProxyUsername();
165         final String proxyPass = cli.getProxyPassword();
166         final String dataDirectory = cli.getDataDirectory();
167         final File propertiesFile = cli.getPropertiesFile();
168         final String suppressionFile = cli.getSuppressionFile();
169         final boolean jarDisabled = cli.isJarDisabled();
170         final boolean archiveDisabled = cli.isArchiveDisabled();
171         final boolean assemblyDisabled = cli.isAssemblyDisabled();
172         final boolean nuspecDisabled = cli.isNuspecDisabled();
173         final boolean nexusDisabled = cli.isNexusDisabled();
174         final String nexusUrl = cli.getNexusUrl();
175         final String databaseDriverName = cli.getDatabaseDriverName();
176         final String databaseDriverPath = cli.getDatabaseDriverPath();
177         final String connectionString = cli.getConnectionString();
178         final String databaseUser = cli.getDatabaseUser();
179         final String databasePassword = cli.getDatabasePassword();
180         final String additionalZipExtensions = cli.getAdditionalZipExtensions();
181         final String pathToMono = cli.getPathToMono();
182 
183         if (propertiesFile != null) {
184             try {
185                 Settings.mergeProperties(propertiesFile);
186             } catch (FileNotFoundException ex) {
187                 final String msg = String.format("Unable to load properties file '%s'", propertiesFile.getPath());
188                 LOGGER.log(Level.SEVERE, msg);
189                 LOGGER.log(Level.FINE, null, ex);
190             } catch (IOException ex) {
191                 final String msg = String.format("Unable to find properties file '%s'", propertiesFile.getPath());
192                 LOGGER.log(Level.SEVERE, msg);
193                 LOGGER.log(Level.FINE, null, ex);
194             }
195         }
196         // We have to wait until we've merged the properties before attempting to set whether we use
197         // the proxy for Nexus since it could be disabled in the properties, but not explicitly stated
198         // on the command line
199         final boolean nexusUsesProxy = cli.isNexusUsesProxy();
200         if (dataDirectory != null) {
201             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
202         } else if (System.getProperty("basedir") != null) {
203             final File dataDir = new File(System.getProperty("basedir"), "data");
204             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
205         } else {
206             final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath());
207             final File base = jarPath.getParentFile();
208             final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
209             final File dataDir = new File(base, sub);
210             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
211         }
212         Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
213         if (proxyUrl != null && !proxyUrl.isEmpty()) {
214             Settings.setString(Settings.KEYS.PROXY_URL, proxyUrl);
215         }
216         if (proxyPort != null && !proxyPort.isEmpty()) {
217             Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
218         }
219         if (proxyUser != null && !proxyUser.isEmpty()) {
220             Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUser);
221         }
222         if (proxyPass != null && !proxyPass.isEmpty()) {
223             Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPass);
224         }
225         if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
226             Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
227         }
228         if (suppressionFile != null && !suppressionFile.isEmpty()) {
229             Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
230         }
231 
232         //File Type Analyzer Settings
233         Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !jarDisabled);
234         Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !archiveDisabled);
235         Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !nuspecDisabled);
236         Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !assemblyDisabled);
237 
238         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !nexusDisabled);
239         if (nexusUrl != null && !nexusUrl.isEmpty()) {
240             Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
241         }
242         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
243         if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
244             Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
245         }
246         if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
247             Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
248         }
249         if (connectionString != null && !connectionString.isEmpty()) {
250             Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
251         }
252         if (databaseUser != null && !databaseUser.isEmpty()) {
253             Settings.setString(Settings.KEYS.DB_USER, databaseUser);
254         }
255         if (databasePassword != null && !databasePassword.isEmpty()) {
256             Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
257         }
258         if (additionalZipExtensions != null && !additionalZipExtensions.isEmpty()) {
259             Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions);
260         }
261         if (pathToMono != null && !pathToMono.isEmpty()) {
262             Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
263         }
264     }
265 }