1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.maven;
19
20 import java.io.BufferedOutputStream;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.ObjectInputStream;
28 import java.io.ObjectOutputStream;
29 import java.io.OutputStream;
30 import java.util.List;
31 import java.util.Locale;
32 import java.util.logging.Level;
33 import java.util.logging.Logger;
34 import org.apache.maven.artifact.Artifact;
35 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
36 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
37 import org.apache.maven.artifact.repository.ArtifactRepository;
38 import org.apache.maven.artifact.versioning.ArtifactVersion;
39 import org.apache.maven.doxia.sink.Sink;
40 import org.apache.maven.plugin.AbstractMojo;
41 import org.apache.maven.plugin.MojoExecutionException;
42 import org.apache.maven.plugin.MojoFailureException;
43 import org.apache.maven.plugins.annotations.Component;
44 import org.apache.maven.plugins.annotations.Parameter;
45 import org.apache.maven.project.MavenProject;
46 import org.apache.maven.reporting.MavenReport;
47 import org.apache.maven.reporting.MavenReportException;
48 import org.apache.maven.settings.Proxy;
49 import org.owasp.dependencycheck.data.nexus.MavenArtifact;
50 import org.owasp.dependencycheck.data.nvdcve.CveDB;
51 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
52 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
53 import org.owasp.dependencycheck.dependency.Confidence;
54 import org.owasp.dependencycheck.dependency.Dependency;
55 import org.owasp.dependencycheck.dependency.Identifier;
56 import org.owasp.dependencycheck.dependency.Vulnerability;
57 import org.owasp.dependencycheck.reporting.ReportGenerator;
58 import org.owasp.dependencycheck.utils.DependencyVersion;
59 import org.owasp.dependencycheck.utils.LogUtils;
60 import org.owasp.dependencycheck.utils.Settings;
61
62
63
64
65
66 public abstract class BaseDependencyCheckMojo extends AbstractMojo implements MavenReport {
67
68
69
70
71
72 private static final Logger LOGGER = Logger.getLogger(BaseDependencyCheckMojo.class.getName());
73
74
75
76 private static final String PROPERTIES_FILE = "mojo.properties";
77
78
79
80 private static final String LOG_PROPERTIES_FILE = "log.properties";
81
82
83
84 private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
85
86
87
88 @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
89 private String dataFileName;
90
91
92
93
94
95
96 @Component
97 private MavenProject project;
98
99
100
101 @Component
102 private ArtifactMetadataSource metadataSource;
103
104
105
106 @Parameter(property = "localRepository", readonly = true)
107 private ArtifactRepository localRepository;
108
109
110
111 @Parameter(property = "project.remoteArtifactRepositories", readonly = true)
112 private List<ArtifactRepository> remoteRepositories;
113
114
115
116 @Parameter(readonly = true, required = true, property = "reactorProjects")
117 private List<MavenProject> reactorProjects;
118
119
120
121 @SuppressWarnings("CanBeFinal")
122 @Parameter(property = "logFile", defaultValue = "")
123 private String logFile = null;
124
125
126
127
128
129 @Parameter(defaultValue = "${project.build.directory}", required = true)
130 private File outputDirectory;
131
132
133
134
135 @Parameter(property = "project.reporting.outputDirectory", required = true)
136 private File reportOutputDirectory;
137
138
139
140
141 @SuppressWarnings("CanBeFinal")
142 @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true)
143 private float failBuildOnCVSS = 11;
144
145
146
147
148 @SuppressWarnings("CanBeFinal")
149 @Parameter(property = "autoupdate", defaultValue = "true", required = true)
150 private boolean autoUpdate = true;
151
152
153
154
155
156 @Parameter(property = "aggregate", defaultValue = "false")
157 @Deprecated
158 private boolean aggregate;
159
160
161
162
163 @SuppressWarnings("CanBeFinal")
164 @Parameter(property = "format", defaultValue = "HTML", required = true)
165 private String format = "HTML";
166
167
168
169 @Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false)
170 private org.apache.maven.settings.Settings mavenSettings;
171
172
173
174
175 @SuppressWarnings("CanBeFinal")
176 @Parameter(property = "mavenSettingsProxyId", required = false)
177 private String mavenSettingsProxyId;
178
179
180
181
182 @SuppressWarnings("CanBeFinal")
183 @Parameter(property = "connectionTimeout", defaultValue = "", required = false)
184 private String connectionTimeout = null;
185
186
187
188 @SuppressWarnings("CanBeFinal")
189 @Parameter(property = "suppressionFile", defaultValue = "", required = false)
190 private String suppressionFile = null;
191
192
193
194 @SuppressWarnings("CanBeFinal")
195 @Parameter(property = "showSummary", defaultValue = "true", required = false)
196 private boolean showSummary = true;
197
198
199
200
201 @SuppressWarnings("CanBeFinal")
202 @Parameter(property = "jarAnalyzerEnabled", defaultValue = "true", required = false)
203 private boolean jarAnalyzerEnabled = true;
204
205
206
207
208 @SuppressWarnings("CanBeFinal")
209 @Parameter(property = "archiveAnalyzerEnabled", defaultValue = "true", required = false)
210 private boolean archiveAnalyzerEnabled = true;
211
212
213
214
215 @SuppressWarnings("CanBeFinal")
216 @Parameter(property = "assemblyAnalyzerEnabled", defaultValue = "true", required = false)
217 private boolean assemblyAnalyzerEnabled = true;
218
219
220
221
222 @SuppressWarnings("CanBeFinal")
223 @Parameter(property = "nuspecAnalyzerEnabled", defaultValue = "true", required = false)
224 private boolean nuspecAnalyzerEnabled = true;
225
226
227
228
229 @SuppressWarnings("CanBeFinal")
230 @Parameter(property = "centralAnalyzerEnabled", defaultValue = "true", required = false)
231 private boolean centralAnalyzerEnabled = true;
232
233
234
235
236 @SuppressWarnings("CanBeFinal")
237 @Parameter(property = "nexusAnalyzerEnabled", defaultValue = "true", required = false)
238 private boolean nexusAnalyzerEnabled = true;
239
240
241
242
243 @Parameter(property = "nexusUrl", defaultValue = "", required = false)
244 private String nexusUrl;
245
246
247
248 @Parameter(property = "nexusUsesProxy", defaultValue = "true", required = false)
249 private boolean nexusUsesProxy = true;
250
251
252
253 @Parameter(property = "connectionString", defaultValue = "", required = false)
254 private String connectionString;
255
256
257
258 @Parameter(property = "databaseDriverName", defaultValue = "", required = false)
259 private String databaseDriverName;
260
261
262
263 @Parameter(property = "databaseDriverPath", defaultValue = "", required = false)
264 private String databaseDriverPath;
265
266
267
268 @Parameter(property = "databaseUser", defaultValue = "", required = false)
269 private String databaseUser;
270
271
272
273 @Parameter(property = "databasePassword", defaultValue = "", required = false)
274 private String databasePassword;
275
276
277
278 @Parameter(property = "zipExtensions", required = false)
279 private String zipExtensions;
280
281
282
283 @SuppressWarnings("CanBeFinal")
284 @Parameter(property = "skipTestScope", defaultValue = "true", required = false)
285 private boolean skipTestScope = true;
286
287
288
289 @SuppressWarnings("CanBeFinal")
290 @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false)
291 private boolean skipRuntimeScope = false;
292
293
294
295 @SuppressWarnings("CanBeFinal")
296 @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false)
297 private boolean skipProvidedScope = false;
298
299
300
301 @Parameter(property = "dataDirectory", defaultValue = "", required = false)
302 private String dataDirectory;
303
304
305
306 @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false)
307 private String cveUrl12Modified;
308
309
310
311 @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false)
312 private String cveUrl20Modified;
313
314
315
316 @Parameter(property = "cveUrl12Base", defaultValue = "", required = false)
317 private String cveUrl12Base;
318
319
320
321 @Parameter(property = "cveUrl20Base", defaultValue = "", required = false)
322 private String cveUrl20Base;
323
324
325
326
327 @Parameter(property = "pathToMono", defaultValue = "", required = false)
328 private String pathToMono;
329
330
331
332
333
334
335 @SuppressWarnings("CanBeFinal")
336 @Parameter(property = "proxyUrl", defaultValue = "", required = false)
337 @Deprecated
338 private String proxyUrl = null;
339
340
341
342
343
344 @SuppressWarnings("CanBeFinal")
345 @Parameter(property = "externalReport")
346 @Deprecated
347 private String externalReport = null;
348
349
350
351
352
353
354
355
356
357 @Override
358 public void execute() throws MojoExecutionException, MojoFailureException {
359 validateAggregate();
360 project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory);
361 runCheck();
362 }
363
364
365
366
367
368
369
370 private void validateAggregate() throws MojoExecutionException {
371 if (aggregate) {
372 final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. "
373 + "Please use the aggregate goal instead.";
374 throw new MojoExecutionException(msg);
375 }
376 }
377
378
379
380
381
382
383
384
385
386 @Deprecated
387 public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
388 generate((Sink) sink, locale);
389 }
390
391
392
393
394
395
396
397
398 public void generate(Sink sink, Locale locale) throws MavenReportException {
399 try {
400 validateAggregate();
401 } catch (MojoExecutionException ex) {
402 throw new MavenReportException(ex.getMessage());
403 }
404 project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory());
405 try {
406 runCheck();
407 } catch (MojoExecutionException ex) {
408 throw new MavenReportException(ex.getMessage(), ex);
409 } catch (MojoFailureException ex) {
410 LOGGER.warning("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build");
411 }
412 }
413
414
415
416
417
418
419
420 protected File getCorrectOutputDirectory() throws MojoExecutionException {
421 return getCorrectOutputDirectory(this.project);
422 }
423
424
425
426
427
428
429
430 protected File getCorrectOutputDirectory(MavenProject current) {
431 final Object obj = current.getContextValue(getOutputDirectoryContextKey());
432 if (obj != null) {
433 if (obj instanceof File) {
434 return (File) obj;
435 }
436 }
437 File target = new File(current.getBuild().getDirectory());
438 if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) {
439 target = target.getParentFile();
440 }
441 return target;
442 }
443
444
445
446
447
448
449
450 protected File getDataFile(MavenProject current) {
451 LOGGER.fine(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey()));
452 final Object obj = current.getContextValue(getDataFileContextKey());
453 if (obj != null) {
454 if (obj instanceof File) {
455 return (File) obj;
456 }
457 } else {
458 LOGGER.fine("Context value not found");
459 }
460 return null;
461 }
462
463
464
465
466
467
468
469 protected void scanArtifacts(MavenProject project, Engine engine) {
470 for (Artifact a : project.getArtifacts()) {
471 if (excludeFromScan(a)) {
472 continue;
473 }
474 final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile());
475 if (deps != null) {
476 if (deps.size() == 1) {
477 final Dependency d = deps.get(0);
478 if (d != null) {
479 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
480 d.addAsEvidence("pom", ma, Confidence.HIGHEST);
481 d.addProjectReference(project.getName());
482 LOGGER.fine(String.format("Adding project reference %s on dependency %s", project.getName(),
483 d.getDisplayFileName()));
484 if (metadataSource != null) {
485 try {
486 final DependencyVersion currentVersion = new DependencyVersion(a.getVersion());
487 final List<ArtifactVersion> versions = metadataSource.retrieveAvailableVersions(a,
488 localRepository, remoteRepositories);
489 for (ArtifactVersion av : versions) {
490 final DependencyVersion newVersion = new DependencyVersion(av.toString());
491 if (currentVersion.compareTo(newVersion) < 0) {
492 d.addAvailableVersion(av.toString());
493 }
494 }
495 } catch (ArtifactMetadataRetrievalException ex) {
496 LOGGER.log(Level.WARNING,
497 "Unable to check for new versions of dependencies; see the log for more details.");
498 LOGGER.log(Level.FINE, null, ex);
499 } catch (Throwable t) {
500 LOGGER.log(Level.WARNING,
501 "Unexpected error occured checking for new versions; see the log for more details.");
502 LOGGER.log(Level.FINE, "", t);
503 }
504 }
505 }
506 } else {
507 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'",
508 a.getGroupId(), a.getArtifactId(), a.getVersion());
509 LOGGER.fine(msg);
510 }
511 }
512 }
513 }
514
515
516
517
518
519
520
521 public abstract void runCheck() throws MojoExecutionException, MojoFailureException;
522
523
524
525
526
527
528 @Override
529 public void setReportOutputDirectory(File directory) {
530 reportOutputDirectory = directory;
531 }
532
533
534
535
536
537
538 @Override
539 public File getReportOutputDirectory() {
540 return reportOutputDirectory;
541 }
542
543
544
545
546
547
548 public File getOutputDirectory() {
549 return outputDirectory;
550 }
551
552
553
554
555
556
557 @Override
558 public final boolean isExternalReport() {
559 return true;
560 }
561
562
563
564
565
566
567 public String getOutputName() {
568 if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) {
569 return "dependency-check-report";
570 } else if ("XML".equalsIgnoreCase(this.format)) {
571 return "dependency-check-report.xml#";
572 } else if ("VULN".equalsIgnoreCase(this.format)) {
573 return "dependency-check-vulnerability";
574 } else {
575 LOGGER.log(Level.WARNING, "Unknown report format used during site generation.");
576 return "dependency-check-report";
577 }
578 }
579
580
581
582
583
584
585 public String getCategoryName() {
586 return MavenReport.CATEGORY_PROJECT_REPORTS;
587 }
588
589
590
591
592
593
594
595
596 protected Engine initializeEngine() throws DatabaseException {
597 final InputStream in = BaseDependencyCheckMojo.class
598 .getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
599 LogUtils.prepareLogger(in, logFile);
600
601 populateSettings();
602
603 return new Engine(this.project,
604 this.reactorProjects);
605 }
606
607
608
609
610
611 private void populateSettings() {
612 Settings.initialize();
613 InputStream mojoProperties = null;
614 try {
615 mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
616 Settings.mergeProperties(mojoProperties);
617 } catch (IOException ex) {
618 LOGGER.log(Level.WARNING, "Unable to load the dependency-check ant task.properties file.");
619 LOGGER.log(Level.FINE, null, ex);
620 } finally {
621 if (mojoProperties != null) {
622 try {
623 mojoProperties.close();
624 } catch (IOException ex) {
625 LOGGER.log(Level.FINEST, null, ex);
626 }
627 }
628 }
629
630 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
631 if (externalReport != null) {
632 LOGGER.warning("The 'externalReport' option was set; this configuration option has been removed. "
633 + "Please update the dependency-check-maven plugin's configuration");
634 }
635
636 if (proxyUrl != null && !proxyUrl.isEmpty()) {
637 LOGGER.warning("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead");
638 }
639 final Proxy proxy = getMavenProxy();
640 if (proxy != null) {
641 Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost());
642 Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort()));
643 final String userName = proxy.getUsername();
644 final String password = proxy.getPassword();
645 if (userName != null) {
646 Settings.setString(Settings.KEYS.PROXY_USERNAME, userName);
647 }
648 if (password != null) {
649 Settings.setString(Settings.KEYS.PROXY_PASSWORD, password);
650 }
651
652 }
653
654 if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
655 Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
656 }
657 if (suppressionFile != null && !suppressionFile.isEmpty()) {
658 Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
659 }
660
661
662
663 Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
664
665 Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
666
667 Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
668
669 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
670 if (nexusUrl != null && !nexusUrl.isEmpty()) {
671 Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
672 }
673 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
674
675 Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
676 if (zipExtensions != null && !zipExtensions.isEmpty()) {
677 Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
678 }
679
680 Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
681 if (pathToMono != null && !pathToMono.isEmpty()) {
682 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
683 }
684
685
686 if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
687 Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
688 }
689 if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
690 Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
691 }
692 if (connectionString != null && !connectionString.isEmpty()) {
693 Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
694 }
695 if (databaseUser != null && !databaseUser.isEmpty()) {
696 Settings.setString(Settings.KEYS.DB_USER, databaseUser);
697 }
698 if (databasePassword != null && !databasePassword.isEmpty()) {
699 Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
700 }
701
702 if (dataDirectory != null && !dataDirectory.isEmpty()) {
703 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
704 }
705
706
707 Settings.setBoolean(Settings.KEYS.SKIP_TEST_SCOPE, skipTestScope);
708 Settings.setBoolean(Settings.KEYS.SKIP_RUNTIME_SCOPE, skipRuntimeScope);
709 Settings.setBoolean(Settings.KEYS.SKIP_PROVIDED_SCOPE, skipProvidedScope);
710
711
712 if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) {
713 Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
714 }
715 if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) {
716 Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
717 }
718 if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) {
719 Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
720 }
721 if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) {
722 Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
723 }
724 }
725
726
727
728
729
730
731 private Proxy getMavenProxy() {
732 if (mavenSettings != null) {
733 final List<Proxy> proxies = mavenSettings.getProxies();
734 if (proxies != null && !proxies.isEmpty()) {
735 if (mavenSettingsProxyId != null) {
736 for (Proxy proxy : proxies) {
737 if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) {
738 return proxy;
739 }
740 }
741 } else if (proxies.size() == 1) {
742 return proxies.get(0);
743 } else {
744 LOGGER.warning("Multiple proxy definitions exist in the Maven settings. In the dependency-check "
745 + "configuration set the mavenSettingsProxyId so that the correct proxy will be used.");
746 throw new IllegalStateException("Ambiguous proxy definition");
747 }
748 }
749 }
750 return null;
751 }
752
753
754
755
756
757
758
759 protected boolean excludeFromScan(Artifact a) {
760 if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
761 return true;
762 }
763 if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) {
764 return true;
765 }
766 if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
767 return true;
768 }
769 return false;
770 }
771
772
773
774
775
776
777
778
779
780 protected MavenProject getProject() {
781 return project;
782 }
783
784
785
786
787
788
789 protected List<MavenProject> getReactorProjects() {
790 return reactorProjects;
791 }
792
793
794
795
796
797
798 protected String getFormat() {
799 return format;
800 }
801
802
803
804
805
806
807
808
809 protected void writeReports(Engine engine, MavenProject p, File outputDir) {
810 DatabaseProperties prop = null;
811 CveDB cve = null;
812 try {
813 cve = new CveDB();
814 cve.open();
815 prop = cve.getDatabaseProperties();
816 } catch (DatabaseException ex) {
817 LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
818 } finally {
819 if (cve != null) {
820 cve.close();
821 }
822 }
823 final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
824 try {
825 r.generateReports(outputDir.getAbsolutePath(), format);
826 } catch (IOException ex) {
827 LOGGER.log(Level.SEVERE,
828 "Unexpected exception occurred during analysis; please see the verbose error log for more details.");
829 LOGGER.log(Level.FINE, null, ex);
830 } catch (Throwable ex) {
831 LOGGER.log(Level.SEVERE,
832 "Unexpected exception occurred during analysis; please see the verbose error log for more details.");
833 LOGGER.log(Level.FINE, null, ex);
834 }
835 }
836
837
838
839
840
841
842
843
844
845 protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException {
846 if (failBuildOnCVSS <= 10) {
847 final StringBuilder ids = new StringBuilder();
848 for (Dependency d : dependencies) {
849 boolean addName = true;
850 for (Vulnerability v : d.getVulnerabilities()) {
851 if (v.getCvssScore() >= failBuildOnCVSS) {
852 if (addName) {
853 addName = false;
854 ids.append(NEW_LINE).append(d.getFileName()).append(": ");
855 ids.append(v.getName());
856 } else {
857 ids.append(", ").append(v.getName());
858 }
859 }
860 }
861 }
862 if (ids.length() > 0) {
863 final String msg = String.format("%n%nDependency-Check Failure:%n"
864 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
865 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
866 throw new MojoFailureException(msg);
867 }
868 }
869 }
870
871
872
873
874
875
876
877 protected void showSummary(MavenProject mp, List<Dependency> dependencies) {
878 if (showSummary) {
879 final StringBuilder summary = new StringBuilder();
880 for (Dependency d : dependencies) {
881 boolean firstEntry = true;
882 final StringBuilder ids = new StringBuilder();
883 for (Vulnerability v : d.getVulnerabilities()) {
884 if (firstEntry) {
885 firstEntry = false;
886 } else {
887 ids.append(", ");
888 }
889 ids.append(v.getName());
890 }
891 if (ids.length() > 0) {
892 summary.append(d.getFileName()).append(" (");
893 firstEntry = true;
894 for (Identifier id : d.getIdentifiers()) {
895 if (firstEntry) {
896 firstEntry = false;
897 } else {
898 summary.append(", ");
899 }
900 summary.append(id.getValue());
901 }
902 summary.append(") : ").append(ids).append(NEW_LINE);
903 }
904 }
905 if (summary.length() > 0) {
906 final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s"
907 + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString());
908 LOGGER.log(Level.WARNING, msg);
909 }
910 }
911 }
912
913
914
915
916
917
918
919
920
921 protected String getDataFileContextKey() {
922 return "dependency-check-path-" + dataFileName;
923 }
924
925
926
927
928
929
930
931 protected String getOutputDirectoryContextKey() {
932 return "dependency-output-dir-" + dataFileName;
933 }
934
935
936
937
938
939
940
941
942 protected void writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) {
943 File file;
944
945 if (mp.getContextValue(this.getDataFileContextKey()) == null) {
946 if (writeTo == null) {
947 file = new File(mp.getBuild().getDirectory());
948 file = new File(file, dataFileName);
949 } else {
950 file = new File(writeTo, dataFileName);
951 }
952 OutputStream os = null;
953 OutputStream bos = null;
954 ObjectOutputStream out = null;
955 try {
956 if (dependencies != null) {
957 os = new FileOutputStream(file);
958 bos = new BufferedOutputStream(os);
959 out = new ObjectOutputStream(bos);
960 out.writeObject(dependencies);
961 out.flush();
962
963
964
965 out.reset();
966 }
967 LOGGER.fine(String.format("Serialized data file written to '%s' for %s, referenced by key %s",
968 file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey()));
969 mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath());
970 } catch (IOException ex) {
971 LOGGER.log(Level.WARNING, "Unable to create data file used for report aggregation; "
972 + "if report aggregation is being used the results may be incomplete.");
973 LOGGER.log(Level.FINE, ex.getMessage(), ex);
974 } finally {
975 if (out != null) {
976 try {
977 out.close();
978 } catch (IOException ex) {
979 LOGGER.log(Level.FINEST, "ignore", ex);
980 }
981 }
982 if (bos != null) {
983 try {
984 bos.close();
985 } catch (IOException ex) {
986 LOGGER.log(Level.FINEST, "ignore", ex);
987 }
988 }
989 if (os != null) {
990 try {
991 os.close();
992 } catch (IOException ex) {
993 LOGGER.log(Level.FINEST, "ignore", ex);
994 }
995 }
996 }
997 }
998 }
999
1000
1001
1002
1003
1004
1005
1006
1007
1008 protected List<Dependency> readDataFile(MavenProject project) {
1009 final Object oPath = project.getContextValue(this.getDataFileContextKey());
1010 if (oPath == null) {
1011 return null;
1012 }
1013 List<Dependency> ret = null;
1014 final String path = (String) oPath;
1015 ObjectInputStream ois = null;
1016 try {
1017 ois = new ObjectInputStream(new FileInputStream(path));
1018 ret = (List<Dependency>) ois.readObject();
1019 } catch (FileNotFoundException ex) {
1020
1021 LOGGER.log(Level.SEVERE, null, ex);
1022 } catch (IOException ex) {
1023 LOGGER.log(Level.SEVERE, null, ex);
1024 } catch (ClassNotFoundException ex) {
1025 LOGGER.log(Level.SEVERE, null, ex);
1026 } finally {
1027 if (ois != null) {
1028 try {
1029 ois.close();
1030 } catch (IOException ex) {
1031 LOGGER.log(Level.SEVERE, null, ex);
1032 }
1033 }
1034 }
1035 return ret;
1036 }
1037
1038 }