/
report.clj
122 lines (108 loc) · 4.75 KB
/
report.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
;; The MIT License (MIT)
;;
;; Copyright (c) 2016- Richard Hull
;;
;; Permission is hereby granted, free of charge, to any person obtaining a copy
;; of this software and associated documentation files (the "Software"), to deal
;; in the Software without restriction, including without limitation the rights
;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
;; copies of the Software, and to permit persons to whom the Software is
;; furnished to do so, subject to the following conditions:
;;
;; The above copyright notice and this permission notice shall be included in all
;; copies or substantial portions of the Software.
;;
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;; SOFTWARE.
(ns nvd.report
(:require
[clojure.string :as s]
[clojure.java.io :as io]
[clansi :refer [style]]
[table.core :refer [table]])
(:import
[java.util Arrays]
[org.owasp.dependencycheck Engine]
[org.owasp.dependencycheck.dependency Dependency Vulnerability]
[org.owasp.dependencycheck.exception ExceptionCollection]
[org.owasp.dependencycheck.reporting ReportGenerator]))
(def default-output-dir "target/nvd")
(defn generate-report [project]
(let [^Engine engine (:engine project)
title (:title project)
output-dir (get-in project [:nvd :output-dir] default-output-dir)
output-fmt (get-in project [:nvd :output-format] "ALL")
db-props (.getDatabaseProperties (.getDatabase engine))
deps (Arrays/asList (.getDependencies engine))
analyzers (.getAnalyzers engine)
settings (.getSettings engine)
exception-collection (ExceptionCollection.)
rg (ReportGenerator. title deps analyzers db-props settings exception-collection)]
(.write rg ^String output-dir ^String output-fmt)
project))
(defn- score [^Vulnerability vulnerability]
(let [cvss2 (.getCvssV2 vulnerability)
cvss3 (.getCvssV3 vulnerability)]
(cond
cvss2 (.getScore cvss2)
cvss3 (.getBaseScore cvss3)
:else 1)))
(defn- severity [^long cvssScore]
(cond
(= cvssScore 0) :none
(< cvssScore 4) :low
(>= cvssScore 7) :high
:else :medium))
(defn- color [severity]
(get {:none :green :low :cyan :medium :yellow :high :red} severity))
(defn- vulnerable? [^Dependency dep]
(not-empty (.getVulnerabilities dep)))
(defn- vuln-status [^Dependency dep]
(if-not (vulnerable? dep)
(style "OK" :green :bright)
(s/join ", "
(for [^Vulnerability v (reverse (sort-by score (.getVulnerabilities dep)))
:let [color (-> v score severity color)]]
(style (.getName v) color :bright)))))
(defn- vulnerabilities [project ^Engine engine]
(sort-by :dependency
(for [^Dependency dep (.getDependencies engine)
:when (or (vulnerable? dep) (:verbose-summary project))]
{:dependency (.getFileName dep) :status (vuln-status dep)})))
(defn- scores [^Engine engine]
(flatten (for [^Dependency dep (.getDependencies engine)
^Vulnerability vuln (.getVulnerabilities dep)]
(score vuln))))
(defn print-summary [project]
(let [^Engine engine (:engine project)
output-dir (get-in project [:nvd :output-dir] default-output-dir)
summary (vulnerabilities project engine)
scores (scores engine)
highest-score (apply max 0 scores)
color (-> highest-score severity color)
severity (-> highest-score severity name s/upper-case)]
(when (or (:verbose-summary project) (pos? (count scores)))
(table summary))
(println)
(print (count scores) "vulnerabilities detected. Severity: ")
(println (style severity color :bright))
(println "Detailed reports saved in:" (style (.getAbsolutePath (io/file output-dir)) :bright))
(let [file (io/file output-dir "dependency-check-report.html")]
(when (-> file .exists)
(println "HTML report :" (style (.getAbsolutePath file) :bright))))
(println)
(println (style " *** THIS REPORT IS WITHOUT WARRANTY ***" :magenta :bright))
project))
(defn fail-build? [project]
(let [^Engine engine (:engine project)
highest-score (long (apply max 0 (scores engine)))
fail-threshold (long (get-in project [:nvd :fail-threshold] 0))]
(->
project
(assoc-in [:nvd :highest-score] highest-score)
(assoc :failed? (> highest-score fail-threshold)))))