nexpose_ticketing 0.0.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/{README.markdown → README.md} +43 -38
- data/bin/nexpose_jira +2 -3
- data/bin/nexpose_remedy +17 -0
- data/bin/nexpose_servicenow +17 -0
- data/lib/nexpose_ticketing.rb +3 -1
- data/lib/nexpose_ticketing/config/remedy.config +26 -0
- data/lib/nexpose_ticketing/config/remedy_wsdl/HPD_IncidentInterface_Create_WS.xml +296 -0
- data/lib/nexpose_ticketing/config/remedy_wsdl/HPD_IncidentInterface_WS.xml +675 -0
- data/lib/nexpose_ticketing/config/servicenow.config +18 -0
- data/lib/nexpose_ticketing/config/ticket_service.config +2 -2
- data/lib/nexpose_ticketing/helpers/jira_helper.rb +6 -6
- data/lib/nexpose_ticketing/helpers/remedy_helper.rb +448 -0
- data/lib/nexpose_ticketing/helpers/servicenow_helper.rb +315 -0
- data/lib/nexpose_ticketing/nx_logger.rb +35 -0
- data/lib/nexpose_ticketing/queries.rb +105 -14
- data/lib/nexpose_ticketing/ticket_repository.rb +57 -12
- data/lib/nexpose_ticketing/ticket_service.rb +56 -19
- data/nexpose_ticketing.gemspec +5 -4
- metadata +29 -4
@@ -5,7 +5,7 @@ module NexposeTicketing
|
|
5
5
|
require 'nexpose'
|
6
6
|
require 'nexpose_ticketing/queries'
|
7
7
|
|
8
|
-
def nexpose_login
|
8
|
+
def nexpose_login(nexpose_data)
|
9
9
|
@nsc = Nexpose::Connection.new(nexpose_data[:nxconsole], nexpose_data[:nxuser], nexpose_data[:nxpasswd])
|
10
10
|
@nsc.login
|
11
11
|
end
|
@@ -32,10 +32,10 @@ module NexposeTicketing
|
|
32
32
|
# - +csv_file_name+ - CSV File name.
|
33
33
|
#
|
34
34
|
def save_last_scans(csv_file_name, saved_file = nil, report_config = Nexpose::AdhocReportConfig.new(nil, 'sql'))
|
35
|
-
report_config.add_filter('version', '1.
|
35
|
+
report_config.add_filter('version', '1.2.0')
|
36
36
|
report_config.add_filter('query', Queries.last_scans)
|
37
37
|
report_output = report_config.generate(@nsc)
|
38
|
-
csv_output = CSV.parse(report_output.chomp, headers: :first_row
|
38
|
+
csv_output = CSV.parse(report_output.chomp, headers: :first_row)
|
39
39
|
saved_file.open(csv_file_name, 'w') { |file| file.puts(csv_output) } unless saved_file.nil?
|
40
40
|
if saved_file.nil?
|
41
41
|
File.open(csv_file_name, 'w') { |file| file.puts(csv_output) }
|
@@ -48,7 +48,7 @@ module NexposeTicketing
|
|
48
48
|
# - A hash with site_ids => last_scan_id
|
49
49
|
#
|
50
50
|
def last_scans(report_config = Nexpose::AdhocReportConfig.new(nil, 'sql'))
|
51
|
-
report_config.add_filter('version', '1.
|
51
|
+
report_config.add_filter('version', '1.2.0')
|
52
52
|
report_config.add_filter('query', Queries.last_scans)
|
53
53
|
report_output = report_config.generate(@nsc).chomp
|
54
54
|
nexpose_sites = Hash.new(-1)
|
@@ -64,13 +64,14 @@ module NexposeTicketing
|
|
64
64
|
# - +site_options+ - A Hash with site(s) and severity level.
|
65
65
|
#
|
66
66
|
# * *Returns* :
|
67
|
-
# - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
67
|
+
# - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
68
|
+
# |url| |summary| |fix|
|
68
69
|
#
|
69
70
|
def all_vulns(site_options = {}, report_config = Nexpose::AdhocReportConfig.new(nil, 'sql'))
|
70
71
|
sites = Array(site_options[:sites])
|
71
72
|
severity = site_options[:severity].nil? ? 0 : site_options[:severity]
|
72
|
-
report_config.add_filter('version', '1.
|
73
|
-
report_config.add_filter('query', Queries.
|
73
|
+
report_config.add_filter('version', '1.2.0')
|
74
|
+
report_config.add_filter('query', Queries.all_new_vulns)
|
74
75
|
unless sites.empty?
|
75
76
|
sites.each do |site_id|
|
76
77
|
report_config.add_filter('site', site_id)
|
@@ -80,21 +81,65 @@ module NexposeTicketing
|
|
80
81
|
report_config.generate(@nsc)
|
81
82
|
end
|
82
83
|
|
83
|
-
# Gets the
|
84
|
+
# Gets the new vulns from base scan reported_scan_id and the newest / latest scan from a site.
|
84
85
|
#
|
85
86
|
# * *Args* :
|
86
87
|
# - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
|
87
88
|
#
|
88
89
|
# * *Returns* :
|
89
|
-
# - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
90
|
+
# - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
91
|
+
# |url| |summary| |fix|
|
90
92
|
#
|
91
|
-
def
|
93
|
+
def new_vulns_sites(site_options = {}, report_config = Nexpose::AdhocReportConfig.new(nil, 'sql'))
|
92
94
|
site = site_options[:site_id]
|
93
95
|
reported_scan_id = site_options[:scan_id]
|
94
96
|
fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
|
95
97
|
severity = site_options[:severity].nil? ? 0 : site_options[:severity]
|
96
|
-
report_config.add_filter('version', '1.
|
97
|
-
report_config.add_filter('query', Queries.
|
98
|
+
report_config.add_filter('version', '1.2.0')
|
99
|
+
report_config.add_filter('query', Queries.new_vulns_since_scan(reported_scan_id))
|
100
|
+
report_config.add_filter('site', site)
|
101
|
+
report_config.add_filter('vuln-severity', severity)
|
102
|
+
report_config.generate(@nsc)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Gets the old vulns from base scan reported_scan_id and the newest / latest scan from a site.
|
106
|
+
#
|
107
|
+
# * *Args* :
|
108
|
+
# - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
|
109
|
+
#
|
110
|
+
# * *Returns* :
|
111
|
+
# - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
112
|
+
# |url| |summary| |fix|
|
113
|
+
#
|
114
|
+
def old_vulns_sites(site_options = {}, report_config = Nexpose::AdhocReportConfig.new(nil, 'sql'))
|
115
|
+
site = site_options[:site_id]
|
116
|
+
reported_scan_id = site_options[:scan_id]
|
117
|
+
fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
|
118
|
+
severity = site_options[:severity].nil? ? 0 : site_options[:severity]
|
119
|
+
report_config.add_filter('version', '1.2.0')
|
120
|
+
report_config.add_filter('query', Queries.old_vulns_since_scan(reported_scan_id))
|
121
|
+
report_config.add_filter('site', site)
|
122
|
+
report_config.add_filter('vuln-severity', severity)
|
123
|
+
report_config.generate(@nsc)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Gets all vulns from base scan reported_scan_id and the newest / latest scan from a site. This is
|
127
|
+
# used for IP-based issue updating. Includes the baseline comparision value ('Old','New', or 'Same').
|
128
|
+
#
|
129
|
+
# * *Args* :
|
130
|
+
# - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
|
131
|
+
#
|
132
|
+
# * *Returns* :
|
133
|
+
# - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
|
134
|
+
# |url| |summary| |fix| |comparison|
|
135
|
+
#
|
136
|
+
def all_vulns_sites(site_options = {}, report_config = Nexpose::AdhocReportConfig.new(nil, 'sql'))
|
137
|
+
site = site_options[:site_id]
|
138
|
+
reported_scan_id = site_options[:scan_id]
|
139
|
+
fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
|
140
|
+
severity = site_options[:severity].nil? ? 0 : site_options[:severity]
|
141
|
+
report_config.add_filter('version', '1.2.0')
|
142
|
+
report_config.add_filter('query', Queries.all_vulns_since_scan(reported_scan_id))
|
98
143
|
report_config.add_filter('site', site)
|
99
144
|
report_config.add_filter('vuln-severity', severity)
|
100
145
|
report_config.generate(@nsc)
|
@@ -53,8 +53,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
53
53
|
require 'fileutils'
|
54
54
|
require 'nexpose_ticketing/ticket_repository'
|
55
55
|
|
56
|
-
TICKET_SERVICE_CONFIG_PATH = File.join(File.dirname(__FILE__),'/config/ticket_service.config')
|
57
|
-
LOGGER_FILE = File.join(File.dirname(__FILE__),'/log/ticket_service.log')
|
56
|
+
TICKET_SERVICE_CONFIG_PATH = File.join(File.dirname(__FILE__), '/config/ticket_service.config')
|
57
|
+
LOGGER_FILE = File.join(File.dirname(__FILE__), '/log/ticket_service.log')
|
58
58
|
|
59
59
|
attr_accessor :helper_data, :nexpose_data, :options, :ticket_repository, :first_time, :nexpose_site_histories
|
60
60
|
|
@@ -75,7 +75,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
75
75
|
|
76
76
|
# Loads all the helpers.
|
77
77
|
log_message('Loading helpers.')
|
78
|
-
Dir[File.join(File.dirname(__FILE__),'/helpers/*.rb')].each do |file|
|
78
|
+
Dir[File.join(File.dirname(__FILE__), '/helpers/*.rb')].each do |file|
|
79
79
|
log_message("Loading helper: #{file}")
|
80
80
|
require_relative file
|
81
81
|
end
|
@@ -103,7 +103,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
103
103
|
end
|
104
104
|
|
105
105
|
# Prepares all the local and nexpose historical data.
|
106
|
-
def prepare_historical_data(ticket_repository, options,
|
106
|
+
def prepare_historical_data(ticket_repository, options,
|
107
|
+
historical_scan_file = File.join(File.dirname(__FILE__), "#{options[:file_name]}"))
|
107
108
|
if File.exists?(historical_scan_file)
|
108
109
|
log_message("Reading historical CSV file: #{historical_scan_file}.")
|
109
110
|
file_site_histories = ticket_repository.read_last_scans(historical_scan_file)
|
@@ -118,20 +119,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
118
119
|
end
|
119
120
|
|
120
121
|
# Generates a full site(s) report ticket(s).
|
121
|
-
def all_site_report(ticket_repository, options, helper,
|
122
|
+
def all_site_report(ticket_repository, options, helper,
|
123
|
+
historical_scan_file = File.join(File.dirname(__FILE__), "#{options[:file_name]}"))
|
122
124
|
log_message('First time run, generating full vulnerability report.') if @first_time
|
123
125
|
log_message('No site(s) specified, generating full vulnerability report.') if options[:sites].empty?
|
124
126
|
all_delta_vulns = ticket_repository.all_vulns(severity: options[:severity])
|
125
127
|
log_message('Preparing tickets.')
|
126
|
-
tickets = helper.
|
127
|
-
helper.
|
128
|
+
tickets = helper.prepare_create_tickets(all_delta_vulns)
|
129
|
+
helper.create_tickets(tickets)
|
128
130
|
log_message("Done processing, updating historical CSV file #{historical_scan_file}.")
|
129
131
|
ticket_repository.save_last_scans(historical_scan_file)
|
130
132
|
log_message('Done updating historical CSV file, service shutting down.')
|
131
133
|
end
|
132
134
|
|
133
135
|
# There's possibly a new scan with new data.
|
134
|
-
def delta_site_report(ticket_repository, options, helper, file_site_histories,
|
136
|
+
def delta_site_report(ticket_repository, options, helper, file_site_histories,
|
137
|
+
historical_scan_file = File.join(File.dirname(__FILE__), "#{options[:file_name]}"))
|
135
138
|
# Compares the Scan information from the File && Nexpose.
|
136
139
|
no_processing = true
|
137
140
|
@nexpose_site_histories.each do |site_id, scan_id|
|
@@ -158,22 +161,56 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
158
161
|
log_message("New site id: #{site_id} detected. Generating report.")
|
159
162
|
new_site_vuln = ticket_repository.all_vulns(sites: [site_id], severity: options[:severity])
|
160
163
|
log_message('Report generated, preparing tickets.')
|
161
|
-
ticket = helper.
|
162
|
-
helper.
|
164
|
+
ticket = helper.prepare_create_tickets(new_site_vuln)
|
165
|
+
helper.create_tickets(ticket)
|
163
166
|
end
|
164
167
|
|
165
168
|
# There's a new scan with possibly new vulnerabilities.
|
166
169
|
def delta_site_new_scan(ticket_repository, site_id, options, helper, file_site_histories)
|
167
170
|
log_message("New scan detected for site: #{site_id}. Generating report.")
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
171
|
+
|
172
|
+
if options[:ticket_mode] == 'I'
|
173
|
+
# I-mode tickets require updating the tickets in the target system.
|
174
|
+
log_message("Scan id for new scan: #{file_site_histories[site_id]}.")
|
175
|
+
all_scan_vuln = ticket_repository.all_vulns_sites(scan_id: file_site_histories[site_id],
|
176
|
+
site_id: site_id,
|
177
|
+
severity: options[:severity])
|
178
|
+
if helper.respond_to?("prepare_update_tickets") && helper.respond_to?("update_tickets")
|
179
|
+
tickets = helper.prepare_update_tickets(all_scan_vuln)
|
180
|
+
helper.update_tickets(tickets)
|
181
|
+
else
|
182
|
+
log_message("Helper does not implement update methods")
|
183
|
+
fail "Helper using 'I' mode must implement prepare_updates and update_tickets"
|
184
|
+
end
|
185
|
+
else
|
186
|
+
# D-mode tickets require creating new tickets and closing old tickets.
|
187
|
+
new_scan_vuln = ticket_repository.new_vulns_sites(scan_id: file_site_histories[site_id], site_id: site_id,
|
188
|
+
severity: options[:severity])
|
189
|
+
preparse = CSV.new(new_scan_vuln.chomp, headers: :first_row)
|
190
|
+
empty_report = preparse.shift.nil?
|
191
|
+
log_message("No new vulnerabilities found in new scan for site: #{site_id}.") if empty_report
|
192
|
+
log_message("New vulnerabilities found in new scan for site #{site_id}, preparing tickets.") unless empty_report
|
193
|
+
unless empty_report
|
194
|
+
tickets = helper.prepare_create_tickets(new_scan_vuln)
|
195
|
+
helper.create_tickets(tickets)
|
196
|
+
end
|
197
|
+
|
198
|
+
if helper.respond_to?("prepare_close_tickets") && helper.respond_to?("close_tickets")
|
199
|
+
old_scan_vuln = ticket_repository.old_vulns_sites(scan_id: file_site_histories[site_id], site_id: site_id,
|
200
|
+
severity: options[:severity])
|
201
|
+
preparse = CSV.new(old_scan_vuln.chomp, headers: :first_row)
|
202
|
+
empty_report = preparse.shift.nil?
|
203
|
+
log_message("No old (closed) vulnerabilities found in new scan for site: #{site_id}.") if empty_report
|
204
|
+
log_message("Old vulnerabilities found in new scan for site #{site_id}, preparing closures.") unless empty_report
|
205
|
+
unless empty_report
|
206
|
+
tickets = helper.prepare_close_tickets(old_scan_vuln)
|
207
|
+
helper.close_tickets(tickets)
|
208
|
+
end
|
209
|
+
else
|
210
|
+
# Create a log message but do not halt execution of the helper if ticket closeing is not
|
211
|
+
# supported to allow legacy code to execute normally.
|
212
|
+
log_message("Helper does not impelment close methods.")
|
213
|
+
end
|
177
214
|
end
|
178
215
|
end
|
179
216
|
|
data/nexpose_ticketing.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'nexpose_ticketing'
|
5
|
-
s.version = '0.
|
5
|
+
s.version = '0.2.1'
|
6
6
|
s.homepage = 'https://github.com/rapid7/nexpose_ticketing'
|
7
7
|
s.summary = 'Ruby Nexpose Ticketing Engine.'
|
8
8
|
s.description = 'This gem provides a Ruby implementation of different integrations with ticketing services for Nexpose.'
|
@@ -11,9 +11,10 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.email = ['damian_finol@rapid7.com']
|
12
12
|
s.files = Dir['[A-Z]*'] + Dir['lib/**/*']
|
13
13
|
s.require_paths = ['lib']
|
14
|
-
s.extra_rdoc_files = ['README.
|
14
|
+
s.extra_rdoc_files = ['README.md']
|
15
15
|
s.required_ruby_version = '>= 1.9'
|
16
16
|
s.platform = 'ruby'
|
17
|
-
s.executables
|
17
|
+
s.executables = ['nexpose_jira','nexpose_servicenow','nexpose_remedy']
|
18
18
|
s.add_dependency('nexpose', '>= 0.6.0')
|
19
|
-
|
19
|
+
s.add_dependency('savon', '~> 2.1')
|
20
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nexpose_ticketing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Damian Finol
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02
|
11
|
+
date: 2014-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nexpose
|
@@ -24,22 +24,47 @@ dependencies:
|
|
24
24
|
- - ! '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.6.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: savon
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.1'
|
27
41
|
description: This gem provides a Ruby implementation of different integrations with
|
28
42
|
ticketing services for Nexpose.
|
29
43
|
email:
|
30
44
|
- damian_finol@rapid7.com
|
31
45
|
executables:
|
32
46
|
- nexpose_jira
|
47
|
+
- nexpose_servicenow
|
48
|
+
- nexpose_remedy
|
33
49
|
extensions: []
|
34
50
|
extra_rdoc_files:
|
35
|
-
- README.
|
51
|
+
- README.md
|
36
52
|
files:
|
37
|
-
- README.
|
53
|
+
- README.md
|
38
54
|
- bin/nexpose_jira
|
55
|
+
- bin/nexpose_remedy
|
56
|
+
- bin/nexpose_servicenow
|
39
57
|
- lib/nexpose_ticketing.rb
|
40
58
|
- lib/nexpose_ticketing/config/jira.config
|
59
|
+
- lib/nexpose_ticketing/config/remedy.config
|
60
|
+
- lib/nexpose_ticketing/config/remedy_wsdl/HPD_IncidentInterface_Create_WS.xml
|
61
|
+
- lib/nexpose_ticketing/config/remedy_wsdl/HPD_IncidentInterface_WS.xml
|
62
|
+
- lib/nexpose_ticketing/config/servicenow.config
|
41
63
|
- lib/nexpose_ticketing/config/ticket_service.config
|
42
64
|
- lib/nexpose_ticketing/helpers/jira_helper.rb
|
65
|
+
- lib/nexpose_ticketing/helpers/remedy_helper.rb
|
66
|
+
- lib/nexpose_ticketing/helpers/servicenow_helper.rb
|
67
|
+
- lib/nexpose_ticketing/nx_logger.rb
|
43
68
|
- lib/nexpose_ticketing/queries.rb
|
44
69
|
- lib/nexpose_ticketing/ticket_repository.rb
|
45
70
|
- lib/nexpose_ticketing/ticket_service.rb
|