nexpose_ticketing 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/nexpose_servicedesk +17 -0
- data/lib/nexpose_ticketing/config/servicedesk.config +19 -0
- data/lib/nexpose_ticketing/config/servicenow.config +1 -1
- data/lib/nexpose_ticketing/config/ticket_service.config +15 -5
- data/lib/nexpose_ticketing/helpers/jira_helper.rb +5 -5
- data/lib/nexpose_ticketing/helpers/remedy_helper.rb +401 -78
- data/lib/nexpose_ticketing/helpers/servicedesk_helper.rb +337 -0
- data/lib/nexpose_ticketing/helpers/servicenow_helper.rb +68 -52
- data/lib/nexpose_ticketing/queries.rb +251 -23
- data/lib/nexpose_ticketing/ticket_repository.rb +151 -8
- data/lib/nexpose_ticketing/ticket_service.rb +80 -37
- metadata +20 -2
@@ -4,6 +4,25 @@ module NexposeTicketing
|
|
4
4
|
# for Nexpose.
|
5
5
|
# Copyright:: Copyright (c) 2014 Rapid7, LLC.
|
6
6
|
module Queries
|
7
|
+
|
8
|
+
# Formats SQL query for riskscore based on user config options.
|
9
|
+
#
|
10
|
+
# * *Args* :
|
11
|
+
# - +riskScore+ - riskscore for assets to match in results of query.
|
12
|
+
#
|
13
|
+
# * *Returns* :
|
14
|
+
# - Returns String - Formatted SQL string for inserting into queries.
|
15
|
+
#
|
16
|
+
def self.createRiskString(riskScore)
|
17
|
+
if riskScore.nil?
|
18
|
+
riskString = ""
|
19
|
+
else
|
20
|
+
riskString = "WHERE fa.riskscore >= #{riskScore}"
|
21
|
+
end
|
22
|
+
return riskString
|
23
|
+
end
|
24
|
+
|
25
|
+
|
7
26
|
# Gets all the latests scans.
|
8
27
|
# Returns |site.id| |last_scan_id| |finished|
|
9
28
|
def self.last_scans
|
@@ -12,15 +31,16 @@ module NexposeTicketing
|
|
12
31
|
JOIN dim_scan dsc ON ds.last_scan_id = dsc.scan_id'
|
13
32
|
end
|
14
33
|
|
15
|
-
|
34
|
+
|
35
|
+
# Gets all delta vulns for all sites sorted by IP.
|
16
36
|
#
|
17
37
|
# * *Returns* :
|
18
38
|
# -Returns |asset_id| |ip_address| |current_scan| |vulnerability_id||solution_id| |nexpose_id|
|
19
39
|
# |url| |summary| |fix|
|
20
40
|
#
|
21
|
-
def self.all_new_vulns
|
41
|
+
def self.all_new_vulns(options = {})
|
22
42
|
"SELECT DISTINCT on (da.ip_address, davs.solution_id) subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id,
|
23
|
-
ds.url,proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix
|
43
|
+
ds.url,proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
|
24
44
|
FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
25
45
|
FROM fact_asset_scan_vulnerability_finding fasv
|
26
46
|
JOIN
|
@@ -34,8 +54,38 @@ module NexposeTicketing
|
|
34
54
|
JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
|
35
55
|
JOIN dim_solution ds USING (solution_id)
|
36
56
|
JOIN dim_asset da ON subs.asset_id = da.asset_id
|
57
|
+
JOIN fact_asset fa ON fa.asset_id = da.asset_id
|
58
|
+
#{createRiskString( options[:riskScore])}
|
37
59
|
ORDER BY da.ip_address, davs.solution_id"
|
38
|
-
|
60
|
+
end
|
61
|
+
|
62
|
+
# Gets all delta vulns for all sites sorted by vuln ID.
|
63
|
+
#
|
64
|
+
# * *Returns* :
|
65
|
+
# -Returns |asset_id| |ip_address| |current_scan| |vulnerability_id||solution_id| |nexpose_id|
|
66
|
+
# |url| |summary| |fix|
|
67
|
+
#
|
68
|
+
def self.all_new_vulns_by_vuln_id(options = {})
|
69
|
+
"SELECT DISTINCT on (subs.vulnerability_id, subs.asset_id, davs.solution_id) subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dv.title, davs.solution_id, ds.nexpose_id,
|
70
|
+
ds.url,proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
|
71
|
+
FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
72
|
+
FROM fact_asset_scan_vulnerability_finding fasv
|
73
|
+
JOIN
|
74
|
+
(
|
75
|
+
SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
|
76
|
+
FROM dim_asset) s
|
77
|
+
ON s.asset_id = fasv.asset_id AND (fasv.scan_id = s.baseline_scan OR fasv.scan_id = s.current_scan)
|
78
|
+
GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan, fasv.scan_id
|
79
|
+
HAVING NOT baselineComparison(fasv.scan_id, current_scan) = 'Old'
|
80
|
+
) subs
|
81
|
+
JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
|
82
|
+
JOIN dim_solution ds USING (solution_id)
|
83
|
+
JOIN dim_asset da ON subs.asset_id = da.asset_id
|
84
|
+
JOIN dim_vulnerability dv ON subs.vulnerability_id = dv.vulnerability_id
|
85
|
+
JOIN fact_asset fa ON fa.asset_id = da.asset_id
|
86
|
+
#{createRiskString(options[:riskScore])}
|
87
|
+
ORDER BY subs.vulnerability_id, subs.asset_id, davs.solution_id"
|
88
|
+
end
|
39
89
|
|
40
90
|
# Gets all new vulnerabilities happening after a reported scan id.
|
41
91
|
#
|
@@ -46,26 +96,61 @@ module NexposeTicketing
|
|
46
96
|
# - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
47
97
|
# |url| |summary| |fix|
|
48
98
|
#
|
49
|
-
def self.new_vulns_since_scan(
|
99
|
+
def self.new_vulns_since_scan(options = {})
|
50
100
|
"SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id,
|
51
|
-
ds.url, proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix
|
101
|
+
ds.url, proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
|
52
102
|
FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
53
103
|
FROM fact_asset_scan_vulnerability_finding fasv
|
54
104
|
JOIN
|
55
105
|
(
|
56
106
|
SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
|
57
107
|
FROM dim_asset) s
|
58
|
-
ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{
|
108
|
+
ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
59
109
|
GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
60
110
|
HAVING baselineComparison(fasv.scan_id, current_scan) = 'New'
|
61
111
|
) subs
|
62
112
|
JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
|
63
113
|
JOIN dim_solution ds USING (solution_id)
|
64
114
|
JOIN dim_asset da ON subs.asset_id = da.asset_id
|
65
|
-
AND subs.current_scan > #{
|
115
|
+
AND subs.current_scan > #{options[:scan_id]}
|
116
|
+
JOIN fact_asset fa ON fa.asset_id = da.asset_id
|
117
|
+
#{createRiskString(options[:riskScore])}
|
66
118
|
ORDER BY da.ip_address"
|
67
119
|
end
|
68
|
-
|
120
|
+
|
121
|
+
|
122
|
+
# Gets all new vulnerabilities happening after a reported scan id. Sorted by vuln ID.
|
123
|
+
#
|
124
|
+
# * *Args* :
|
125
|
+
# - +reported_scan+ - Last reported scan id.
|
126
|
+
#
|
127
|
+
# * *Returns* :
|
128
|
+
# - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
129
|
+
# |url| |summary| |fix|
|
130
|
+
#
|
131
|
+
def self.new_vulns_by_vuln_id_since_scan(options = {})
|
132
|
+
"SELECT DISTINCT on (subs.vulnerability_id, subs.asset_id, davs.solution_id) subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id,
|
133
|
+
ds.url, proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
|
134
|
+
FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
135
|
+
FROM fact_asset_scan_vulnerability_finding fasv
|
136
|
+
JOIN
|
137
|
+
(
|
138
|
+
SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
|
139
|
+
FROM dim_asset) s
|
140
|
+
ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
141
|
+
GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
142
|
+
HAVING baselineComparison(fasv.scan_id, current_scan) = 'New'
|
143
|
+
) subs
|
144
|
+
JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
|
145
|
+
JOIN dim_solution ds USING (solution_id)
|
146
|
+
JOIN dim_asset da ON subs.asset_id = da.asset_id
|
147
|
+
AND subs.current_scan > #{options[:scan_id]}
|
148
|
+
JOIN fact_asset fa ON fa.asset_id = da.asset_id
|
149
|
+
#{createRiskString(options[:riskScore])}
|
150
|
+
ORDER BY subs.vulnerability_id, subs.asset_id, davs.solution_id"
|
151
|
+
end
|
152
|
+
|
153
|
+
|
69
154
|
# Gets all old vulnerabilities happening after a reported scan id.
|
70
155
|
#
|
71
156
|
# * *Args* :
|
@@ -75,26 +160,29 @@ module NexposeTicketing
|
|
75
160
|
# - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
76
161
|
# |url| |summary| |fix|
|
77
162
|
#
|
78
|
-
def self.old_vulns_since_scan(
|
163
|
+
def self.old_vulns_since_scan(options = {})
|
79
164
|
"SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dvs.solution_id, ds.nexpose_id, ds.url,
|
80
|
-
proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison
|
165
|
+
proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
|
81
166
|
FROM (
|
82
167
|
SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
|
83
168
|
FROM fact_asset_scan_vulnerability_finding fasv
|
84
169
|
JOIN (
|
85
170
|
SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
|
86
171
|
FROM dim_asset
|
87
|
-
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{
|
172
|
+
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
88
173
|
GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
89
174
|
HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
|
90
175
|
) subs
|
91
176
|
JOIN dim_vulnerability_solution dvs USING (vulnerability_id)
|
92
177
|
JOIN dim_solution ds USING (solution_id)
|
93
178
|
JOIN dim_asset da ON subs.asset_id = da.asset_id
|
94
|
-
AND subs.current_scan > #{
|
179
|
+
AND subs.current_scan > #{options[:scan_id]}
|
180
|
+
JOIN fact_asset fa ON fa.asset_id = da.asset_id
|
181
|
+
#{createRiskString(options[:riskScore])}
|
95
182
|
ORDER BY da.ip_address"
|
96
183
|
end
|
97
|
-
|
184
|
+
|
185
|
+
|
98
186
|
# Gets all vulnerabilities happening after a reported scan id. This result set also includes the
|
99
187
|
# baseline comparision ("Old", "New", or "Same") allowing for IP-based ticket updating.
|
100
188
|
#
|
@@ -105,28 +193,30 @@ module NexposeTicketing
|
|
105
193
|
# - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
106
194
|
# |url| |summary| |fix| |comparison|
|
107
195
|
#
|
108
|
-
def self.all_vulns_since_scan(
|
196
|
+
def self.all_vulns_since_scan(options = {})
|
109
197
|
"SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dvs.solution_id, ds.nexpose_id, ds.url,
|
110
|
-
proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison
|
198
|
+
proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
|
111
199
|
FROM (
|
112
|
-
SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
|
200
|
+
SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
|
113
201
|
FROM fact_asset_scan_vulnerability_finding fasv
|
114
202
|
JOIN (
|
115
203
|
SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
|
116
204
|
FROM dim_asset
|
117
|
-
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{
|
205
|
+
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
118
206
|
GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
119
207
|
HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
|
120
208
|
) subs
|
121
209
|
JOIN dim_vulnerability_solution dvs USING (vulnerability_id)
|
122
210
|
JOIN dim_solution ds USING (solution_id)
|
123
211
|
JOIN dim_asset da ON subs.asset_id = da.asset_id
|
124
|
-
|
212
|
+
JOIN fact_asset fa ON fa.asset_id = subs.asset_id
|
213
|
+
#{createRiskString(options[:riskScore])}
|
214
|
+
AND subs.current_scan > #{options[:scan_id]}
|
125
215
|
|
126
216
|
UNION
|
127
217
|
|
128
218
|
SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id, ds.url,
|
129
|
-
proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison
|
219
|
+
proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
|
130
220
|
FROM
|
131
221
|
(
|
132
222
|
SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
|
@@ -135,17 +225,155 @@ module NexposeTicketing
|
|
135
225
|
(
|
136
226
|
SELECT asset_id,lastScan(asset_id) AS current_scan
|
137
227
|
FROM dim_asset
|
138
|
-
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{
|
228
|
+
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
139
229
|
GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
140
230
|
HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
|
141
231
|
) subs
|
142
232
|
JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
|
143
233
|
JOIN dim_solution ds USING (solution_id)
|
144
234
|
JOIN dim_asset da ON subs.asset_id = da.asset_id
|
145
|
-
|
235
|
+
JOIN fact_asset fa ON fa.asset_id = subs.asset_id
|
236
|
+
#{createRiskString(options[:riskScore])}
|
237
|
+
AND subs.current_scan > #{options[:scan_id]}
|
146
238
|
|
147
239
|
ORDER BY ip_address, comparison"
|
148
240
|
end
|
149
|
-
|
241
|
+
|
242
|
+
# Gets all vulnerabilities happening after a reported scan id. Sorted by vuln ID. This result set also includes the
|
243
|
+
# baseline comparision ("Old", "New", or "Same") allowing for IP-based ticket updating.
|
244
|
+
#
|
245
|
+
# * *Args* :
|
246
|
+
# - +reported_scan+ - Last reported scan id.
|
247
|
+
#
|
248
|
+
# * *Returns* :
|
249
|
+
# - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
250
|
+
# |url| |summary| |fix| |comparison|
|
251
|
+
#
|
252
|
+
def self.all_vulns_by_vuln_id_since_scan(options = {})
|
253
|
+
"SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dv.title, dvs.solution_id, ds.nexpose_id, ds.url,
|
254
|
+
proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
|
255
|
+
FROM (
|
256
|
+
SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
|
257
|
+
FROM fact_asset_scan_vulnerability_finding fasv
|
258
|
+
JOIN (
|
259
|
+
SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
|
260
|
+
FROM dim_asset
|
261
|
+
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
262
|
+
GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
263
|
+
HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
|
264
|
+
) subs
|
265
|
+
JOIN dim_vulnerability_solution dvs USING (vulnerability_id)
|
266
|
+
JOIN dim_solution ds USING (solution_id)
|
267
|
+
JOIN dim_asset da ON subs.asset_id = da.asset_id
|
268
|
+
JOIN dim_vulnerability dv ON subs.vulnerability_id = dv.vulnerability_id
|
269
|
+
JOIN fact_asset fa ON fa.asset_id = subs.asset_id
|
270
|
+
#{createRiskString(options[:riskScore])}
|
271
|
+
AND subs.current_scan > #{options[:scan_id]}
|
272
|
+
|
273
|
+
UNION
|
274
|
+
|
275
|
+
SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dv.title, davs.solution_id, ds.nexpose_id, ds.url,
|
276
|
+
proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
|
277
|
+
FROM
|
278
|
+
(
|
279
|
+
SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
|
280
|
+
FROM fact_asset_scan_vulnerability_finding fasv
|
281
|
+
JOIN
|
282
|
+
(
|
283
|
+
SELECT asset_id,lastScan(asset_id) AS current_scan
|
284
|
+
FROM dim_asset
|
285
|
+
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
286
|
+
GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
|
287
|
+
HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
|
288
|
+
) subs
|
289
|
+
JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
|
290
|
+
JOIN dim_solution ds USING (solution_id)
|
291
|
+
JOIN dim_asset da ON subs.asset_id = da.asset_id
|
292
|
+
JOIN dim_vulnerability dv ON subs.vulnerability_id = dv.vulnerability_id
|
293
|
+
JOIN fact_asset fa ON fa.asset_id = subs.asset_id
|
294
|
+
#{createRiskString(options[:riskScore])}
|
295
|
+
AND subs.current_scan > #{options[:scan_id]}
|
296
|
+
|
297
|
+
ORDER BY vulnerability_id, comparison, asset_id, solution_id"
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
# Gets all IP addresses that have only old vulnerabilities i.e. any open tickets can be closed.
|
302
|
+
#
|
303
|
+
# * *Args* :
|
304
|
+
# - +reported_scan+ - Last reported scan id.
|
305
|
+
#
|
306
|
+
# * *Returns* :
|
307
|
+
# - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |comparison|
|
308
|
+
#
|
309
|
+
def self.old_tickets_by_ip(options = {})
|
310
|
+
"SELECT subs.asset_id, subs.ip_address, subs.current_scan, subs.vulnerability_id, subs.comparison
|
311
|
+
FROM (
|
312
|
+
SELECT fasv.asset_id, s.ip_address, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
|
313
|
+
FROM fact_asset_scan_vulnerability_finding fasv
|
314
|
+
JOIN (
|
315
|
+
SELECT asset_id, ip_address, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
|
316
|
+
FROM dim_asset
|
317
|
+
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
318
|
+
GROUP BY fasv.asset_id, fasv.vulnerability_id, s.ip_address, s.current_scan
|
319
|
+
HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
|
320
|
+
) AS subs
|
321
|
+
WHERE subs.ip_address NOT IN (
|
322
|
+
|
323
|
+
SELECT s.ip_address
|
324
|
+
FROM fact_asset_scan_vulnerability_finding fasv
|
325
|
+
JOIN
|
326
|
+
(
|
327
|
+
SELECT asset_id, ip_address, lastScan(asset_id) AS current_scan
|
328
|
+
FROM dim_asset
|
329
|
+
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
330
|
+
GROUP BY s.ip_address, s.current_scan
|
331
|
+
HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
|
332
|
+
)
|
333
|
+
AND subs.current_scan > #{options[:scan_id]}
|
334
|
+
ORDER BY subs.ip_address"
|
335
|
+
end
|
336
|
+
|
337
|
+
|
338
|
+
# Gets all old vulns that have no active IPs i.e. any open tickets in vuln mode ('V') can be closed.
|
339
|
+
#
|
340
|
+
# * *Args* :
|
341
|
+
# - +reported_scan+ - Last reported scan id.
|
342
|
+
#
|
343
|
+
# * *Returns* :
|
344
|
+
# - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |comparison|
|
345
|
+
#
|
346
|
+
def self.old_tickets_by_vuln_id(options = {})
|
347
|
+
"SELECT subs.vulnerability_id, subs.asset_id, subs.ip_address, subs.current_scan, subs.comparison
|
348
|
+
FROM (
|
349
|
+
SELECT fasv.asset_id, s.ip_address, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison, fa.riskscore
|
350
|
+
FROM fact_asset_scan_vulnerability_finding fasv
|
351
|
+
JOIN (
|
352
|
+
SELECT asset_id, ip_address, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
|
353
|
+
FROM dim_asset
|
354
|
+
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
355
|
+
JOIN fact_asset fa ON fa.asset_id = fasv.asset_id
|
356
|
+
#{createRiskString(options[:riskScore])}
|
357
|
+
GROUP BY fasv.asset_id, fasv.vulnerability_id, s.ip_address, s.current_scan, fa.riskscore
|
358
|
+
HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
|
359
|
+
) AS subs
|
360
|
+
WHERE subs.vulnerability_id NOT IN (
|
361
|
+
|
362
|
+
SELECT fasv.vulnerability_id
|
363
|
+
FROM fact_asset_scan_vulnerability_finding fasv
|
364
|
+
JOIN
|
365
|
+
(
|
366
|
+
SELECT da.asset_id, da.ip_address, lastScan(da.asset_id) AS current_scan, fa.riskscore
|
367
|
+
FROM dim_asset da
|
368
|
+
JOIN fact_asset fa ON fa.asset_id = da.asset_id
|
369
|
+
#{createRiskString(options[:riskScore])}
|
370
|
+
) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
|
371
|
+
GROUP BY fasv.vulnerability_id, s.ip_address, s.current_scan
|
372
|
+
HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
|
373
|
+
|
374
|
+
)
|
375
|
+
AND subs.current_scan > #{options[:scan_id]}
|
376
|
+
ORDER BY subs.vulnerability_id"
|
377
|
+
end
|
150
378
|
end
|
151
379
|
end
|
@@ -71,7 +71,7 @@ module NexposeTicketing
|
|
71
71
|
trimmed_csv = []
|
72
72
|
trimmed_csv << report_output.lines.first
|
73
73
|
csv_output.each do |row|
|
74
|
-
if sites.include? row
|
74
|
+
if sites.include? row[0].to_s
|
75
75
|
trimmed_csv << row
|
76
76
|
end
|
77
77
|
end
|
@@ -118,18 +118,34 @@ module NexposeTicketing
|
|
118
118
|
if site_override.nil?
|
119
119
|
sites = Array(options[:sites])
|
120
120
|
else
|
121
|
-
sites = site_override
|
121
|
+
sites = Array(site_override)
|
122
122
|
end
|
123
123
|
report_config = @report_helper.generate_sql_report_config()
|
124
124
|
severity = options[:severity].nil? ? 0 : options[:severity]
|
125
125
|
report_config.add_filter('version', '1.2.0')
|
126
|
-
|
127
|
-
|
126
|
+
if options[:ticket_mode] == 'V'
|
127
|
+
report_config.add_filter('query', Queries.all_new_vulns_by_vuln_id(options))
|
128
|
+
else
|
129
|
+
report_config.add_filter('query', Queries.all_new_vulns(options))
|
130
|
+
end
|
131
|
+
unless sites.nil? || sites.empty?
|
128
132
|
Array(sites).each do |site_id|
|
129
133
|
report_config.add_filter('site', site_id)
|
130
134
|
end
|
131
135
|
end
|
132
136
|
report_config.add_filter('vuln-severity', severity)
|
137
|
+
|
138
|
+
vuln_filter_cats = createVulnerabilityFilter(options)
|
139
|
+
vuln_filer_tags = createTagFilters(options)
|
140
|
+
|
141
|
+
if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
|
142
|
+
report_config.add_filter('vuln-categories', vuln_filter_cats)
|
143
|
+
end
|
144
|
+
|
145
|
+
if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
|
146
|
+
vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
|
147
|
+
end
|
148
|
+
|
133
149
|
@report_helper.save_generate_cleanup_report_config(report_config)
|
134
150
|
end
|
135
151
|
|
@@ -149,9 +165,25 @@ module NexposeTicketing
|
|
149
165
|
fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
|
150
166
|
severity = site_options[:severity].nil? ? 0 : site_options[:severity]
|
151
167
|
report_config.add_filter('version', '1.2.0')
|
152
|
-
|
168
|
+
if site_options[:ticket_mode] == 'V'
|
169
|
+
report_config.add_filter('query', Queries.new_vulns_by_vuln_id_since_scan(site_options))
|
170
|
+
else
|
171
|
+
report_config.add_filter('query', Queries.new_vulns_since_scan(site_options))
|
172
|
+
end
|
153
173
|
report_config.add_filter('site', site)
|
154
174
|
report_config.add_filter('vuln-severity', severity)
|
175
|
+
|
176
|
+
vuln_filter_cats = createVulnerabilityFilter(site_options)
|
177
|
+
vuln_filer_tags = createTagFilters(site_options)
|
178
|
+
|
179
|
+
if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
|
180
|
+
report_config.add_filter('vuln-categories', vuln_filter_cats)
|
181
|
+
end
|
182
|
+
|
183
|
+
if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
|
184
|
+
vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
|
185
|
+
end
|
186
|
+
|
155
187
|
@report_helper.save_generate_cleanup_report_config(report_config)
|
156
188
|
end
|
157
189
|
|
@@ -171,12 +203,63 @@ module NexposeTicketing
|
|
171
203
|
fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
|
172
204
|
severity = site_options[:severity].nil? ? 0 : site_options[:severity]
|
173
205
|
report_config.add_filter('version', '1.2.0')
|
174
|
-
report_config.add_filter('query', Queries.old_vulns_since_scan(
|
206
|
+
report_config.add_filter('query', Queries.old_vulns_since_scan(site_options))
|
175
207
|
report_config.add_filter('site', site)
|
176
208
|
report_config.add_filter('vuln-severity', severity)
|
209
|
+
|
210
|
+
vuln_filter_cats = createVulnerabilityFilter(site_options)
|
211
|
+
vuln_filer_tags = createTagFilters(site_options)
|
212
|
+
|
213
|
+
if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
|
214
|
+
report_config.add_filter('vuln-categories', vuln_filter_cats)
|
215
|
+
end
|
216
|
+
|
217
|
+
if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
|
218
|
+
vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
|
219
|
+
end
|
220
|
+
|
177
221
|
@report_helper.save_generate_cleanup_report_config(report_config)
|
178
222
|
end
|
179
|
-
|
223
|
+
|
224
|
+
# Gets information on possible tickets to close based on only having old vulns/IPs and no new/same ones.
|
225
|
+
# Based on IP address (for 'I' mode) or vuln ID ('V' mode).
|
226
|
+
#
|
227
|
+
# * *Args* :
|
228
|
+
# - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
|
229
|
+
#
|
230
|
+
# * *Returns* :
|
231
|
+
# - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |comparison|
|
232
|
+
#
|
233
|
+
def tickets_to_close(site_options = {})
|
234
|
+
report_config = @report_helper.generate_sql_report_config()
|
235
|
+
site = site_options[:site_id]
|
236
|
+
reported_scan_id = site_options[:scan_id]
|
237
|
+
fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
|
238
|
+
severity = site_options[:severity].nil? ? 0 : site_options[:severity]
|
239
|
+
report_config.add_filter('version', '1.2.0')
|
240
|
+
if site_options[:ticket_mode] == 'V'
|
241
|
+
report_config.add_filter('query', Queries.old_tickets_by_vuln_id(site_options))
|
242
|
+
else
|
243
|
+
report_config.add_filter('query', Queries.old_tickets_by_ip(site_options))
|
244
|
+
end
|
245
|
+
report_config.add_filter('site', site)
|
246
|
+
report_config.add_filter('vuln-severity', severity)
|
247
|
+
|
248
|
+
vuln_filter_cats = createVulnerabilityFilter(site_options)
|
249
|
+
vuln_filer_tags = createTagFilters(site_options)
|
250
|
+
|
251
|
+
if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
|
252
|
+
report_config.add_filter('vuln-categories', vuln_filter_cats)
|
253
|
+
end
|
254
|
+
|
255
|
+
if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
|
256
|
+
vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
|
257
|
+
end
|
258
|
+
|
259
|
+
@report_helper.save_generate_cleanup_report_config(report_config)
|
260
|
+
end
|
261
|
+
|
262
|
+
|
180
263
|
# Gets all vulns from base scan reported_scan_id and the newest / latest scan from a site. This is
|
181
264
|
# used for IP-based issue updating. Includes the baseline comparision value ('Old','New', or 'Same').
|
182
265
|
#
|
@@ -194,10 +277,70 @@ module NexposeTicketing
|
|
194
277
|
fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
|
195
278
|
severity = site_options[:severity].nil? ? 0 : site_options[:severity]
|
196
279
|
report_config.add_filter('version', '1.2.0')
|
197
|
-
|
280
|
+
if site_options[:ticket_mode] == 'V'
|
281
|
+
report_config.add_filter('query', Queries.all_vulns_by_vuln_id_since_scan(site_options))
|
282
|
+
else
|
283
|
+
report_config.add_filter('query', Queries.all_vulns_since_scan(site_options))
|
284
|
+
end
|
198
285
|
report_config.add_filter('site', site)
|
199
286
|
report_config.add_filter('vuln-severity', severity)
|
287
|
+
|
288
|
+
vuln_filter_cats = createVulnerabilityFilter(site_options)
|
289
|
+
vuln_filer_tags = createTagFilters(site_options)
|
290
|
+
|
291
|
+
if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
|
292
|
+
report_config.add_filter('vuln-categories', vuln_filter_cats)
|
293
|
+
end
|
294
|
+
|
295
|
+
if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
|
296
|
+
vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
|
297
|
+
end
|
298
|
+
|
200
299
|
@report_helper.save_generate_cleanup_report_config(report_config)
|
201
300
|
end
|
301
|
+
|
302
|
+
|
303
|
+
# Parses user-configured vulnerability filter categories and returns aforementioned categories in a
|
304
|
+
# format used by the Nexpose::AdhocReportConfig class.
|
305
|
+
#
|
306
|
+
# * *Args* :
|
307
|
+
# - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
|
308
|
+
#
|
309
|
+
# * *Returns* :
|
310
|
+
# - Returns String @vulnerability_categories
|
311
|
+
#
|
312
|
+
def createVulnerabilityFilter(options = {})
|
313
|
+
@vulnerability_categories = nil
|
314
|
+
if options.has_key?(:vulnerabilityCategories)
|
315
|
+
if not options[:vulnerabilityCategories].nil? and not options[:vulnerabilityCategories].empty?
|
316
|
+
@vulnerability_categories = options[:vulnerabilityCategories].strip.split(',').map {|category| "include:#{category}"}.join(',')
|
317
|
+
end
|
318
|
+
end
|
319
|
+
@vulnerability_categories
|
320
|
+
end
|
321
|
+
|
322
|
+
# Parses user-configured tags and returns aforementioned tags in an array containing
|
323
|
+
# strings in the format used by the Nexpose::AdhocReportConfig class.
|
324
|
+
#
|
325
|
+
# * *Args* :
|
326
|
+
# - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
|
327
|
+
#
|
328
|
+
# * *Returns* :
|
329
|
+
# - Returns Array @definedTags
|
330
|
+
#
|
331
|
+
def createTagFilters(options = {})
|
332
|
+
@defined_tags = nil
|
333
|
+
if options.has_key?(:tags)
|
334
|
+
if not options[:tags].nil? and not options[:tags].empty?
|
335
|
+
## Split the tags into an array
|
336
|
+
tag_strings = options[:tags].strip.split(',')
|
337
|
+
|
338
|
+
## Grab the tag info for the ones we are looking for (if the exist in Nexpose).
|
339
|
+
@defined_tags = @nsc.list_tags.select {|nexposeTag| tag_strings.include?(nexposeTag.name)}
|
340
|
+
end
|
341
|
+
end
|
342
|
+
@defined_tags
|
343
|
+
end
|
344
|
+
|
202
345
|
end
|
203
346
|
end
|