Class: NexposeTicketing::TicketRepository
- Inherits:
-
Object
- Object
- NexposeTicketing::TicketRepository
- Defined in:
- lib/nexpose_ticketing/ticket_repository.rb
Overview
Repository class that creates and returns generated reports.
Constant Summary collapse
- API_VERSION =
'1.2.0'
Instance Method Summary collapse
-
#all_site_details ⇒ Object
Returns an array of all sites in the users environment.
- #create_solution_hash(options, nexpose_item) ⇒ Object
- #create_solution_hash_by_ip(options, nexpose_item) ⇒ Object
- #create_solution_hash_by_vuln_id(options, nexpose_item) ⇒ Object
-
#createVulnerabilityFilter(options = {}) ⇒ Object
Parses user-configured vulnerability filter categories and returns aforementioned categories in a format used by the Nexpose::AdhocReportConfig class.
- #define_query_methods ⇒ Object
- #delta_scan_by_ip(options) ⇒ Object
- #delta_scan_by_vuln_id(options) ⇒ Object
- #generate_config(query_name, options, nexpose_items) ⇒ Object
-
#generate_delta_csv(options, close_tickets) ⇒ Object
Method converts retrieved information from Nexpose, sorted by the current state, into a CSV to be parsed into tickets for sending to a third party service.
- #generate_delta_csv_by_ip(options, close_tickets) ⇒ Object
- #generate_delta_csv_by_vuln_id(options, close_tickets) ⇒ Object
-
#generate_delta_scan_data(options) ⇒ Object
Method retrieves current state of a site from Nexpose, before creating a diff against the state the last time the integration was run.
-
#generate_initial_scan_data(options, nexpose_item) ⇒ Object
Method retrieves current state of a site / tag from Nexpose for use in a Ticketing Integration.
- #generate_tag_asset_list(options = {}) ⇒ Object
- #get_asset_ip(asset_id) ⇒ Object
- #get_asset_list(item, mode) ⇒ Object
-
#get_previous_state(options, query_name) ⇒ Object
Returns the previous state of a site.
- #get_site_asset_list(site_id) ⇒ Object
- #get_solution_data ⇒ Object
- #get_tag_asset_list(tag_id) ⇒ Object
- #get_vuln_instances(asset_id, severity = 0) ⇒ Object
- #initial_scan_by_ip(options, nexpose_item) ⇒ Object
- #initial_scan_by_vuln_id(options, nexpose_item) ⇒ Object
-
#initialize(options = nil) ⇒ TicketRepository
constructor
A new instance of TicketRepository.
-
#last_scans(options = {}) ⇒ Object
Gets the last scan information from nexpose sans the CSV headers.
-
#load_last_scans(options = {}) ⇒ Object
Loads the last scan info to memory.
- #log_debug_message(message) ⇒ Object
-
#log_message(message) ⇒ Object
Logs a message if logging is enabled.
- #method_missing(name, *args, &block) ⇒ Object
- #nexpose_login(nexpose_data) ⇒ Object
-
#read_last_scans(csv_file_name) ⇒ Object
Reads a nexpose identifier (tag ID, site ID etc) scan history from disk.
- #read_tag_asset_list(csv_file_name) ⇒ Object
- #request_query(query_name, options = {}, nexpose_items = nil) ⇒ Object
-
#save_last_scans(csv_file_name, options = {}, saved_file = nil) ⇒ Object
Saves the last scan info to disk.
-
#save_to_file(csv_file_name, trimmed_csv, saved_file = nil) ⇒ Object
Saves CSV scan information to disk.
Constructor Details
#initialize(options = nil) ⇒ TicketRepository
Returns a new instance of TicketRepository.
14 15 16 17 18 19 20 21 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 14 def initialize( = nil) @timeout = [:timeout] # Gets the suffix of the query method signatures based on the mode @method_suffix = [:query_suffix] define_query_methods end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
839 840 841 842 843 844 845 846 847 848 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 839 def method_missing(name, *args, &block) full_method_name = "#{name}#{@method_suffix}" unless Queries.respond_to? full_method_name fail %Q{Query request "#{full_method_name}" not understood} end %Q{Creating query request "#{full_method_name}".} request_query(full_method_name, args[0], args[1]) end |
Instance Method Details
#all_site_details ⇒ Object
Returns an array of all sites in the users environment.
-
Returns :
-
An array of Nexpose::SiteSummary objects.
-
614 615 616 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 614 def all_site_details @nsc.sites end |
#create_solution_hash(options, nexpose_item) ⇒ Object
81 82 83 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 81 def create_solution_hash(, nexpose_item) self.send("create_solution_hash#{@method_suffix}", , nexpose_item) end |
#create_solution_hash_by_ip(options, nexpose_item) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 85 def create_solution_hash_by_ip(, nexpose_item) report = all_new_vulns(, nexpose_item) info = {} CSV.foreach(report) do |row| asset_id, vulnerability_id, first_discov, most_recently_discov, solution_ids = row next if asset_id == 'asset_id' unless info.key? asset_id.to_s info[asset_id.to_s] = {} end info[asset_id.to_s][vulnerability_id.to_s] = { first_discovered: first_discov, most_recently: most_recently_discov, solution_ids: solution_ids } end info end |
#create_solution_hash_by_vuln_id(options, nexpose_item) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 106 def create_solution_hash_by_vuln_id(, nexpose_item) report = all_new_vulns(, nexpose_item) info = {} CSV.foreach(report) do |row| vulnerability_id, solution_ids, references = row next if vulnerability_id == 'vulnerability_id' unless info.key? vulnerability_id.to_i info[vulnerability_id.to_i] = {} end info[vulnerability_id.to_i] = { solution_ids: solution_ids, refs: references } end info end |
#createVulnerabilityFilter(options = {}) ⇒ Object
Parses user-configured vulnerability filter categories and returns aforementioned categories in a format used by the Nexpose::AdhocReportConfig class.
-
Args :
-
options
- A Hash with site(s), reported_scan_id and severity level.
-
-
Returns :
-
Returns String @vulnerability_categories
-
726 727 728 729 730 731 732 733 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 726 def createVulnerabilityFilter( = {}) if [:vulnerabilityCategories].nil? || [:vulnerabilityCategories].empty? return nil end filter = [:vulnerabilityCategories].strip.split(',') filter.map { |category| "include:#{category}" }.join(',') end |
#define_query_methods ⇒ Object
23 24 25 26 27 28 29 30 31 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 23 def define_query_methods methods = Queries.methods.grep Regexp.new (@method_suffix+'$') methods.each do |m| define_singleton_method m do |, override=nil| request_query(m, , override) end end end |
#delta_scan_by_ip(options) ⇒ Object
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 245 def delta_scan_by_ip() current_vuln_instances = {} current_vuln_ids = {} ignored_assets = [] assets = if [:tag_run] [Nexpose::Asset.load(@nsc, [:nexpose_item])] else get_site_asset_list([:nexpose_item]) end assets.each do |asset| risk_score = if [:tag_run] asset.assessment.risk_score else asset.risk_score end if risk_score < ([:riskScore] || 0) ignored_assets << asset.id next end vulns = get_vuln_instances(asset.id, [:severity]) current_vuln_instances[asset.id.to_s] = { asset: asset, vulns: vulns } current_vuln_ids[asset.id.to_s] = vulns.map { |v| v.console_id } end state = {} previous_state_file = get_previous_state(, 'last_scan_state_by_ip') CSV.foreach(previous_state_file, headers: true) do |row| asset_id = row['asset_id'].to_s vuln_id = row['vulnerability_id'].to_i next if ignored_assets.include? asset_id if current_vuln_ids.key? asset_id unless state.key? asset_id.to_s state[asset_id] = { asset: current_vuln_instances[asset_id][:asset], new: [], same: [], old: [] } end success = current_vuln_ids[asset_id].delete(vuln_id) if success.nil? state[asset_id][:old] << vuln_id else vulns = current_vuln_instances[asset_id][:vulns] state[asset_id][:same] << vulns.find { |v| v.console_id == vuln_id } end else unless state.key? asset_id state[asset_id] = { old_ticket: '', new: [], same: [], old: [] } end state[asset_id][:old] << vuln_id end end current_vuln_ids.each_key do |asset_id| asset_id = asset_id.to_s unless state.key? asset_id state[asset_id] = { asset: current_vuln_instances[asset_id][:asset], new: [], same: [], old: [] } end current_vuln_ids[asset_id].each do |vuln_id| vulns = current_vuln_instances[asset_id][:vulns] state[asset_id][:new] << vulns.find { |v| v.console_id == vuln_id } end end state.each_key do |asset_id| if state[asset_id][:new].size == 0 && state[asset_id][:same].size == 0 state[asset_id][:old_ticket] = '' end end state end |
#delta_scan_by_vuln_id(options) ⇒ Object
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 328 def delta_scan_by_vuln_id() current_vuln_instances = {} current_vuln_ids = {} ignored_assets = [] assets = get_site_asset_list([:nexpose_item]) assets.each do |asset| if asset.risk_score < ([:riskScore] || 0) ignored_assets << asset.id next end vulns = get_vuln_instances(asset.id.to_s, [:severity]) vulns.each do |vuln| console_id = vuln.console_id unless current_vuln_instances.key? console_id current_vuln_instances[console_id] = { vuln: vuln.id, assets: {} } current_vuln_ids[console_id] = [] end current_vuln_instances[console_id][:assets][asset.id] = asset current_vuln_ids[console_id] << asset.id end end state = {} previous_state_file = get_previous_state(, 'last_scan_state_by_vuln_id') CSV.foreach(previous_state_file, headers: true) do |row| vuln_id = row['vulnerability_id'].to_i asset_ids = row['asset_ids'][1..-2].split(',').map(&:to_i) if current_vuln_ids.key? vuln_id unless state.key? vuln_id state[vuln_id] = { vuln: current_vuln_instances[vuln_id][:vuln], new: [], same: [], old: [] } end asset_ids.each do |asset_id| next if ignored_assets.include? asset_id success = current_vuln_ids[vuln_id].delete(asset_id) if success.nil? asset_info = { id: asset_id, ip: get_asset_ip(asset_id) } state[vuln_id][:old] << asset_info else asset = current_vuln_instances[vuln_id][:assets][asset_id] state[vuln_id][:same] << asset end end else unless state.key? vuln_id state[vuln_id] = { vuln: vuln_id, old_ticket: 1, new: [], same: [], old: [] } end state[vuln_id][:old] << asset_ids end end current_vuln_ids.each_key do |vuln_id| unless state.key? vuln_id state[vuln_id] = { vuln: current_vuln_instances[vuln_id][:vuln], new: [], same: [], old: [] } end current_vuln_ids[vuln_id].each do |asset_id| asset = current_vuln_instances[vuln_id][:assets][asset_id] state[vuln_id][:new] << asset end end state.each_key do |vuln_id| if state[vuln_id][:new].size == 0 && state[vuln_id][:same].size == 0 state[vuln_id][:old_ticket] = 1 end end state end |
#generate_config(query_name, options, nexpose_items) ⇒ Object
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 800 def generate_config(query_name, , nexpose_items) report_config = @report_helper.generate_sql_report_config() nexpose_item = [:nexpose_item] reported_scan_id = [:scan_id] # If it's a non-initial run, we need the last scan ID unless [:initial_run] fail 'Nexpose item cannot be null or empty' if nexpose_item.nil? || reported_scan_id.nil? end report_config.add_filter('version', '2.0.0') report_config.add_filter('query', Queries.send(query_name, )) id_type = if [:report_type].to_s == 'initial' 'tag' elsif [:tag_run] 'device' else 'site' end if nexpose_items != nil && !nexpose_items.empty? nexpose_items.each { |id| report_config.add_filter(id_type, id) } else item = [:tag_run] ? [:tag] : nexpose_item report_config.add_filter(id_type, item) end report_config.add_filter('vuln-severity', [:severity] || 0) vuln_filter_cats = createVulnerabilityFilter() unless vuln_filter_cats.nil? || vuln_filter_cats.empty? report_config.add_filter('vuln-categories', vuln_filter_cats) end @report_helper.save_generate_cleanup_report_config(report_config) end |
#generate_delta_csv(options, close_tickets) ⇒ Object
Method converts retrieved information from Nexpose, sorted by the current state, into a CSV to be parsed into tickets for sending to a third party service
Params:
-
options: The options to use to generate information
-
close_tickets: Whether the user has ticket closures enabled
Returns: A CSV containing all necessary information to create tickets
423 424 425 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 423 def generate_delta_csv(, close_tickets) self.send("generate_delta_csv#{@method_suffix}", , close_tickets) end |
#generate_delta_csv_by_ip(options, close_tickets) ⇒ Object
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 427 def generate_delta_csv_by_ip(, close_tickets) nexpose_item = [:nexpose_item] state = generate_delta_scan_data() info_hash = create_solution_hash(, nexpose_item) delta_scan_file = Tempfile.new("delta_vulnerable_items_#{nexpose_item}") delta_scan_file.binmode CSV.open(delta_scan_file, 'wb') do |csv| csv << ['asset_id', 'vulnerability_id', 'first_discovered', 'most_recently_discovered', 'ip_address', 'riskscore', 'vuln_nexpose_id', 'cvss_score', 'solution_ids', 'comparison'] state.each do |asset_id, vulns| asset = vulns[:asset] asset_id = asset.id.to_s if [:tag_run] address = asset.ip risk_score = asset.assessment.risk_score else address = asset.address risk_score = asset.risk_score end if vulns.key? :new vulns[:new].each do |vuln| info = info_hash[asset_id][vuln.console_id.to_s] csv << [asset_id, vuln.console_id, info[:first_discovered], info[:most_recently], address, risk_score, vuln.id, vuln.cvss_score, info[:solution_ids], 'New'] end end if vulns.key? :same vulns[:same].each do |vuln| info = info_hash[asset_id][vuln.console_id.to_s] csv << [asset_id, vuln.console_id, info[:first_discovered], info[:most_recently], address, risk_score, vuln.id, vuln.cvss_score, info[:solution_ids], 'Same'] end end end end delta_scan_file.flush unless close_tickets return { new_csv: delta_scan_file } end old_vulns_file = Tempfile.new("delta_vuln_old_items_#{nexpose_item}") old_vulns_file.binmode old_vulns_mode = [:old_vulns_mode] CSV.open(old_vulns_file, 'wb') do |csv| csv << %w(asset_id vulnerability_id ip_address) if old_vulns_mode == 'old' key = old_vulns_mode.intern old_vulns = state.select { |asset_id, vulns| vulns[key].size > 0 } old_vulns.each do |asset_id, vulns| asset = old_vulns[asset_id][:asset] vulns[:old].each do |vuln| csv << [asset_id, vuln, asset.address] end end else key = old_vulns_mode.intern old_vulns = state.select{ |asset_id, vulns| vulns.key? key } old_vulns.each do |asset_id, vulns| ip = if vulns.key? :asset vulns[:asset].address else get_asset_ip(asset_id) end csv << [asset_id, '', ip] end end end old_vulns_file.flush { new_csv: delta_scan_file, old_csv: old_vulns_file } end |
#generate_delta_csv_by_vuln_id(options, close_tickets) ⇒ Object
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 512 def generate_delta_csv_by_vuln_id(, close_tickets) nexpose_item = [:nexpose_item] state = generate_delta_scan_data() info = create_solution_hash(, nexpose_item) delta_scan_file = Tempfile.new("delta_vulnerable_items_#{nexpose_item}") delta_scan_file.binmode old_tickets = [] CSV.open(delta_scan_file, 'wb') do |csv| csv << ['vulnerability_id', 'vuln_nexpose_id', 'title', 'cvss_score', 'assets', 'description', 'solution_ids', 'references', 'comparison'] state.each do |vuln_id, data| if data.has_key? :old_ticket old_tickets << vuln_id next end vuln = data[:vuln] vuln_def = Nexpose::VulnerabilityDefinition.load(@nsc, vuln) if data[:new].count > 0 assets = [] data[:new].each do |asset| assets << "#{asset.id}|#{asset.address}|#{asset.risk_score}" end csv << [vuln_id, vuln, vuln_def.title, vuln_def.cvss_score, assets.join('~'), vuln_def.description, info[vuln_id][:solution_ids], info[vuln_id][:refs], 'New'] if data[:same].count > 0 assets = [] data[:same].each do |asset| assets << "#{asset.id}|#{asset.address}|#{asset.risk_score}" end csv << [vuln_id, vuln, vuln_def.title, vuln_def.cvss_score, assets.join('~'), '', '', '', 'Same'] end elsif data[:same].count > 0 assets = [] data[:same].each do |asset| assets << "#{asset.id}|#{asset.address}|#{asset.risk_score}" end csv << [vuln_id, vuln, vuln_def.title, vuln_def.cvss_score, assets.join('~'), vuln_def.description, info[vuln_id][:solution_ids], info[vuln_id][:refs], 'Same'] end if data[:old].count > 0 assets = [] data[:old].each do |asset| assets << "#{asset[:id]}|#{asset[:ip]}|" end csv << [vuln_id, vuln, vuln_def.title, vuln_def.cvss_score, assets.join('~'), '', '', '', 'Old'] end end end delta_scan_file.flush unless close_tickets return { new_csv: delta_scan_file } end old_vulns_file = Tempfile.new("delta_vuln_old_items_#{nexpose_item}") old_vulns_file.binmode CSV.open(old_vulns_file, 'wb') do |csv| csv << %w(vulnerability_id) old_tickets.each { |id| csv << [id] } end old_vulns_file.flush { new_csv: delta_scan_file, old_csv: old_vulns_file } end |
#generate_delta_scan_data(options) ⇒ Object
Method retrieves current state of a site from Nexpose, before creating a diff against the state the last time the integration was run.
Params:
-
Options: The options to use to generate information
Returns: The current state of vulnerabilities for assets in a site.
241 242 243 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 241 def generate_delta_scan_data() self.send("delta_scan#{@method_suffix}", ) end |
#generate_initial_scan_data(options, nexpose_item) ⇒ Object
Method retrieves current state of a site / tag from Nexpose for use in a Ticketing Integration
Params:
-
Options: The options to use to generate information
-
Nexpose_Item: The ID of the Site / Tag to generate data for
Returns: CSV containing vulnerability information
132 133 134 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 132 def generate_initial_scan_data(, nexpose_item) self.send("initial_scan#{@method_suffix}", , nexpose_item) end |
#generate_tag_asset_list(options = {}) ⇒ Object
743 744 745 746 747 748 749 750 751 752 753 754 755 756 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 743 def generate_tag_asset_list( = {}) = Array([:tags]).map!(&:to_s) .each do |t| trimmed_csv = ['asset_id, last_scan_id'] assets = Nexpose::Tag.load(@nsc, t).asset_ids assets.each do |a| scan = @nsc.asset_scan_history(a).max_by { |s| s.scan_id } trimmed_csv << "#{a},#{scan.scan_id}" end save_to_file([:csv_file], trimmed_csv) end end |
#get_asset_ip(asset_id) ⇒ Object
77 78 79 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 77 def get_asset_ip(asset_id) Nexpose::Asset.load(@nsc, asset_id).ip end |
#get_asset_list(item, mode) ⇒ Object
61 62 63 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 61 def get_asset_list(item, mode) self.send("get_#{mode}_asset_list", item) end |
#get_previous_state(options, query_name) ⇒ Object
Returns the previous state of a site
594 595 596 597 598 599 600 601 602 603 604 605 606 607 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 594 def get_previous_state(, query_name) report_config = @report_helper.generate_sql_report_config() report_config.add_filter('version', API_VERSION) report_config.add_filter('query', Queries.send(query_name, )) if [:tag_run] report_config.add_filter('device', [:nexpose_item].to_s) else report_config.add_filter('site', [:nexpose_item]) end report_config.add_filter('vuln-severity', [:severity] || 0) @report_helper.save_generate_cleanup_report_config(report_config) end |
#get_site_asset_list(site_id) ⇒ Object
65 66 67 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 65 def get_site_asset_list(site_id) @nsc.assets(site_id) end |
#get_solution_data ⇒ Object
54 55 56 57 58 59 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 54 def get_solution_data report_config = @report_helper.generate_sql_report_config() report_config.add_filter('version', API_VERSION) report_config.add_filter('query', Queries.all_solutions) @report_helper.save_generate_cleanup_report_config(report_config) end |
#get_tag_asset_list(tag_id) ⇒ Object
69 70 71 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 69 def get_tag_asset_list(tag_id) Nexpose::Tag.load(@nsc, tag_id).asset_ids end |
#get_vuln_instances(asset_id, severity = 0) ⇒ Object
73 74 75 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 73 def get_vuln_instances(asset_id, severity = 0) @nsc.list_device_vulns(asset_id).select {|vuln| vuln.severity >= severity} end |
#initial_scan_by_ip(options, nexpose_item) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 136 def initial_scan_by_ip(, nexpose_item) "Getting vuln info for #{[:scan_mode]}: " \ "#{nexpose_item}" = .dup [:report_type] = 'initial' if [:tag_run] info_hash = create_solution_hash_by_ip(, nexpose_item) "Getting assets for #{nexpose_item}" assets = get_asset_list(nexpose_item, [:scan_mode]) initial_scan_file = Tempfile.new("vulnerable_items_#{nexpose_item}") initial_scan_file.binmode 'Creating CSV for helper' CSV.open(initial_scan_file, 'wb') do |csv| csv << ['asset_id', 'vulnerability_id', 'first_discovered', 'most_recently_discovered', 'ip_address', 'riskscore', 'vuln_nexpose_id', 'cvss_score', 'solution_ids'] assets.each do |asset| if [:tag_run] asset_id = asset.to_s asset_deets = Nexpose::Asset.load(@nsc, asset) address = asset_deets.ip risk_score = asset_deets.assessment.risk_score else asset_id = asset.id.to_s address = asset.address risk_score = asset.risk_score end next if risk_score < ([:riskScore] || 0) "Getting vulns for asset #{address}" vulns = get_vuln_instances(asset_id, [:severity]) vulns.each do |vuln| info = info_hash[asset_id][vuln.console_id.to_s] csv << [asset_id, vuln.console_id, info[:first_discovered], info[:most_recently], address, risk_score, vuln.id, vuln.cvss_score, info[:solution_ids]] end end end initial_scan_file.flush initial_scan_file end |
#initial_scan_by_vuln_id(options, nexpose_item) ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 185 def initial_scan_by_vuln_id(, nexpose_item) "Getting vuln info for #{[:scan_mode]}: " \ "#{nexpose_item}" soln_ref_hash = create_solution_hash_by_vuln_id(, nexpose_item) "Getting assets for #{nexpose_item}" assets = get_asset_list(nexpose_item, [:scan_mode]) current_vuln_instances = {} assets.each do |asset| next if asset.risk_score < ([:riskScore] || 0) vulns = get_vuln_instances(asset.id.to_s, [:severity]) vulns.each do |vuln| unless current_vuln_instances.key? vuln.console_id current_vuln_instances[vuln.console_id] = { vuln: vuln.id, assets: [] } end current_vuln_instances[vuln.console_id][:assets] << asset end end initial_scan_file = Tempfile.new("vulnerable_items_#{nexpose_item}") initial_scan_file.binmode 'Creating CSV for helper' CSV.open(initial_scan_file, 'wb') do |csv| csv << ['vulnerability_id', 'vuln_nexpose_id', 'title', 'cvss_score', 'assets', 'description', 'solution_ids', 'references'] current_vuln_instances.each do |vuln_id, data| vuln_def = Nexpose::VulnerabilityDefinition.load(@nsc, data[:vuln]) assets = [] data[:assets].each do |asset| assets << "#{asset.id}|#{asset.address}|#{asset.risk_score}" end csv << [vuln_id, data[:vuln], vuln_def.title, vuln_def.cvss_score, assets.join('~'), vuln_def.description, soln_ref_hash[vuln_id][:solution_ids], soln_ref_hash[vuln_id][:refs]] end end initial_scan_file.flush initial_scan_file end |
#last_scans(options = {}) ⇒ Object
Gets the last scan information from nexpose sans the CSV headers.
-
Returns :
-
A hash with nexpose_ids (site ID or tag ID) => last_scan_id
-
779 780 781 782 783 784 785 786 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 779 def last_scans( = {}) nexpose_ids= Hash.new(-1) trimmed_csv = load_last_scans() trimmed_csv.drop(1).each do |row| nexpose_ids[row[0]] = row[1] end nexpose_ids end |
#load_last_scans(options = {}) ⇒ Object
Loads the last scan info to memory.
-
Args :
-
csv_file_name
- CSV File name.
-
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 649 def load_last_scans( = {}) @nsc.login if [:tag_run] # Need a scan ID for every asset associated with that tag = Array([:tags]).map!(&:to_s) scan_details = CSV.generate do |csv| csv << %w(tag_id asset_id last_scan_id scan_finished) .each do |t| assets = Nexpose::Tag.load(@nsc, t).asset_ids assets.each do |a| latest = @nsc.asset_scan_history(a).max_by { |s| s.scan_id } csv << [t, a, latest.scan_id, latest.end_time] end end end else sites = Array([:sites]).map!(&:to_s) scan_details = CSV.generate do |csv| csv << %w(site_id last_scan_id finished) sites.each do |s| scan = @nsc.last_scan(s) csv << [s, scan.scan_id, scan.end_time] end end end csv_output = CSV.parse(scan_details.chomp, headers: :first_row) #We only care about sites we are monitoring. trimmed_csv = [] if([:tag_run]) trimmed_csv << 'tag_id,last_scan_fingerprint' current_tag_id = nil tag_finger_print = '' csv_output.each do |row| if (.include? row[0].to_s) && (row[0].to_i != current_tag_id) if(current_tag_id.nil?) #Initial run current_tag_id = row[0].to_i else #New tag ID, finish off the old fingerprint and start on the new one trimmed_csv << CSV::Row.new('tag_id,last_scan_fingerprint'.split(','), "#{current_tag_id},#{Digest::MD5::hexdigest(tag_finger_print)}".split(',')) tag_finger_print.clear current_tag_id = row[0].to_i end end if(current_tag_id == row[0].to_i) #yield current_tag_id, row[1].to_s, row[2].to_s if block_given? tag_finger_print << row[1].to_s tag_finger_print << row[2].to_s end end unless tag_finger_print.empty? trimmed_csv << CSV::Row.new('tag_id,last_scan_fingerprint'.split(','), "#{current_tag_id},#{Digest::MD5::hexdigest(tag_finger_print)}".split(',')) end else trimmed_csv << scan_details.lines.first csv_output.each do |row| trimmed_csv << row end end trimmed_csv end |
#log_debug_message(message) ⇒ Object
50 51 52 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 50 def () @log.() end |
#log_message(message) ⇒ Object
Logs a message if logging is enabled.
46 47 48 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 46 def () @log.() end |
#nexpose_login(nexpose_data) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 33 def nexpose_login(nexpose_data) @nsc = Nexpose::Connection.new(nexpose_data[:nxconsole], nexpose_data[:nxuser], nexpose_data[:nxpasswd]) @nsc.login @log = NexposeTicketing::NxLogger.instance @log.on_connect(nexpose_data[:nxconsole], 3780, @nsc.session_id, '{}') #After login, create the report helper @report_helper = NexposeReportHelper::ReportOps.new(@nsc, @timeout) end |
#read_last_scans(csv_file_name) ⇒ Object
Reads a nexpose identifier (tag ID, site ID etc) scan history from disk.
-
Args :
-
csv_file_name
- CSV File name.
-
-
Returns :
-
A hash with site_ids => last_scan_id
-
626 627 628 629 630 631 632 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 626 def read_last_scans(csv_file_name) file_identifier_histories = Hash.new(-1) CSV.foreach(csv_file_name, headers: true) do |row| file_identifier_histories[row[0]] = row[1] end file_identifier_histories end |
#read_tag_asset_list(csv_file_name) ⇒ Object
735 736 737 738 739 740 741 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 735 def read_tag_asset_list(csv_file_name) file_identifier_histories = Hash.new(-1) CSV.foreach(csv_file_name, headers: true) do |row| file_identifier_histories[row[0]] = row[1] end file_identifier_histories end |
#request_query(query_name, options = {}, nexpose_items = nil) ⇒ Object
788 789 790 791 792 793 794 795 796 797 798 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 788 def request_query(query_name, = {}, nexpose_items = nil) items = if nexpose_items Array(nexpose_items) elsif [:nexpose_item] nil else ["#{[:scan_mode]}s".intern] end report_config = generate_config(query_name, , items) end |
#save_last_scans(csv_file_name, options = {}, saved_file = nil) ⇒ Object
Saves the last scan info to disk.
-
Args :
-
csv_file_name
- CSV File name.
-
639 640 641 642 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 639 def save_last_scans(csv_file_name, = {}, saved_file = nil) current_scan_state = load_last_scans() save_to_file(csv_file_name, current_scan_state, saved_file) end |
#save_to_file(csv_file_name, trimmed_csv, saved_file = nil) ⇒ Object
Saves CSV scan information to disk
-
Args :
-
csv_file_name
- CSV File name.
-
763 764 765 766 767 768 769 770 771 772 |
# File 'lib/nexpose_ticketing/ticket_repository.rb', line 763 def save_to_file(csv_file_name, trimmed_csv, saved_file = nil) unless saved_file.nil? saved_file.open(csv_file_name, 'w') { |file| file.puts(trimmed_csv) } return end dir = File.dirname(csv_file_name) FileUtils.mkdir_p(dir) unless File.directory?(dir) File.open(csv_file_name, 'w') { |file| file.puts(trimmed_csv) } end |