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          try {
61              Settings.initialize();
62              final App app = new App();
63              app.run(args);
64          } finally {
65              Settings.cleanup(true);
66          }
67      }
68  
69      /**
70       * Main CLI entry-point into the application.
71       *
72       * @param args the command line arguments
73       */
74      public void run(String[] args) {
75          final CliParser cli = new CliParser();
76  
77          try {
78              cli.parse(args);
79          } catch (FileNotFoundException ex) {
80              System.err.println(ex.getMessage());
81              cli.printHelp();
82              return;
83          } catch (ParseException ex) {
84              System.err.println(ex.getMessage());
85              cli.printHelp();
86              return;
87          }
88  
89          final InputStream in = App.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
90          LogUtils.prepareLogger(in, cli.getVerboseLog());
91  
92          if (cli.isGetVersion()) {
93              cli.printVersionInfo();
94          } else if (cli.isRunScan()) {
95              populateSettings(cli);
96              runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles());
97          } else {
98              cli.printHelp();
99          }
100     }
101 
102     /**
103      * Scans the specified directories and writes the dependency reports to the reportDirectory.
104      *
105      * @param reportDirectory the path to the directory where the reports will be written
106      * @param outputFormat the output format of the report
107      * @param applicationName the application name for the report
108      * @param files the files/directories to scan
109      */
110     private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files) {
111         Engine scanner = null;
112         try {
113             scanner = new Engine();
114 
115             for (String file : files) {
116                 scanner.scan(file);
117             }
118 
119             scanner.analyzeDependencies();
120             final List<Dependency> dependencies = scanner.getDependencies();
121             DatabaseProperties prop = null;
122             CveDB cve = null;
123             try {
124                 cve = new CveDB();
125                 cve.open();
126                 prop = cve.getDatabaseProperties();
127             } catch (DatabaseException ex) {
128                 LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
129             } finally {
130                 if (cve != null) {
131                     cve.close();
132                 }
133             }
134             final ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop);
135             try {
136                 report.generateReports(reportDirectory, outputFormat);
137             } catch (IOException ex) {
138                 LOGGER.log(Level.SEVERE, "There was an IO error while attempting to generate the report.");
139                 LOGGER.log(Level.FINE, null, ex);
140             } catch (Throwable ex) {
141                 LOGGER.log(Level.SEVERE, "There was an error while attempting to generate the report.");
142                 LOGGER.log(Level.FINE, null, ex);
143             }
144         } catch (DatabaseException ex) {
145             LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
146             LOGGER.log(Level.FINE, "", ex);
147         } finally {
148             if (scanner != null) {
149                 scanner.cleanup();
150             }
151         }
152     }
153 
154     /**
155      * Updates the global Settings.
156      *
157      * @param cli a reference to the CLI Parser that contains the command line arguments used to set the corresponding
158      * settings in the core engine.
159      */
160     private void populateSettings(CliParser cli) {
161 
162         final boolean autoUpdate = cli.isAutoUpdate();
163         final String connectionTimeout = cli.getConnectionTimeout();
164         final String proxyServer = cli.getProxyServer();
165         final String proxyPort = cli.getProxyPort();
166         final String proxyUser = cli.getProxyUsername();
167         final String proxyPass = cli.getProxyPassword();
168         final String dataDirectory = cli.getDataDirectory();
169         final File propertiesFile = cli.getPropertiesFile();
170         final String suppressionFile = cli.getSuppressionFile();
171         final boolean jarDisabled = cli.isJarDisabled();
172         final boolean archiveDisabled = cli.isArchiveDisabled();
173         final boolean assemblyDisabled = cli.isAssemblyDisabled();
174         final boolean nuspecDisabled = cli.isNuspecDisabled();
175         final boolean nexusDisabled = cli.isNexusDisabled();
176         final String nexusUrl = cli.getNexusUrl();
177         final String databaseDriverName = cli.getDatabaseDriverName();
178         final String databaseDriverPath = cli.getDatabaseDriverPath();
179         final String connectionString = cli.getConnectionString();
180         final String databaseUser = cli.getDatabaseUser();
181         final String databasePassword = cli.getDatabasePassword();
182         final String additionalZipExtensions = cli.getAdditionalZipExtensions();
183         final String pathToMono = cli.getPathToMono();
184 
185         if (propertiesFile != null) {
186             try {
187                 Settings.mergeProperties(propertiesFile);
188             } catch (FileNotFoundException ex) {
189                 final String msg = String.format("Unable to load properties file '%s'", propertiesFile.getPath());
190                 LOGGER.log(Level.SEVERE, msg);
191                 LOGGER.log(Level.FINE, null, ex);
192             } catch (IOException ex) {
193                 final String msg = String.format("Unable to find properties file '%s'", propertiesFile.getPath());
194                 LOGGER.log(Level.SEVERE, msg);
195                 LOGGER.log(Level.FINE, null, ex);
196             }
197         }
198         // We have to wait until we've merged the properties before attempting to set whether we use
199         // the proxy for Nexus since it could be disabled in the properties, but not explicitly stated
200         // on the command line
201         final boolean nexusUsesProxy = cli.isNexusUsesProxy();
202         if (dataDirectory != null) {
203             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
204         } else if (System.getProperty("basedir") != null) {
205             final File dataDir = new File(System.getProperty("basedir"), "data");
206             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
207         } else {
208             final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath());
209             final File base = jarPath.getParentFile();
210             final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
211             final File dataDir = new File(base, sub);
212             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
213         }
214         Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
215         if (proxyServer != null && !proxyServer.isEmpty()) {
216             Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
217         }
218         if (proxyPort != null && !proxyPort.isEmpty()) {
219             Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
220         }
221         if (proxyUser != null && !proxyUser.isEmpty()) {
222             Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUser);
223         }
224         if (proxyPass != null && !proxyPass.isEmpty()) {
225             Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPass);
226         }
227         if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
228             Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
229         }
230         if (suppressionFile != null && !suppressionFile.isEmpty()) {
231             Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
232         }
233 
234         //File Type Analyzer Settings
235         Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !jarDisabled);
236         Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !archiveDisabled);
237         Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !nuspecDisabled);
238         Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !assemblyDisabled);
239 
240         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !nexusDisabled);
241         if (nexusUrl != null && !nexusUrl.isEmpty()) {
242             Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
243         }
244         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
245         if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
246             Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
247         }
248         if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
249             Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
250         }
251         if (connectionString != null && !connectionString.isEmpty()) {
252             Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
253         }
254         if (databaseUser != null && !databaseUser.isEmpty()) {
255             Settings.setString(Settings.KEYS.DB_USER, databaseUser);
256         }
257         if (databasePassword != null && !databasePassword.isEmpty()) {
258             Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
259         }
260         if (additionalZipExtensions != null && !additionalZipExtensions.isEmpty()) {
261             Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions);
262         }
263         if (pathToMono != null && !pathToMono.isEmpty()) {
264             Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
265         }
266     }
267 }