nexpose 7.0.0 → 7.0.1
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/CHANGELOG.md +2 -3
- data/Gemfile.lock +1 -1
- data/lib/nexpose/ajax.rb +12 -16
- data/lib/nexpose/alert.rb +20 -21
- data/lib/nexpose/api.rb +3 -3
- data/lib/nexpose/asset.rb +23 -23
- data/lib/nexpose/blackout.rb +6 -14
- data/lib/nexpose/common.rb +87 -92
- data/lib/nexpose/connection.rb +8 -10
- data/lib/nexpose/console.rb +9 -9
- data/lib/nexpose/dag.rb +2 -2
- data/lib/nexpose/data_table.rb +8 -12
- data/lib/nexpose/device.rb +35 -34
- data/lib/nexpose/discovery.rb +69 -69
- data/lib/nexpose/discovery/filter.rb +7 -8
- data/lib/nexpose/engine.rb +22 -21
- data/lib/nexpose/error.rb +7 -5
- data/lib/nexpose/external.rb +21 -16
- data/lib/nexpose/filter.rb +51 -52
- data/lib/nexpose/global_blackout.rb +6 -7
- data/lib/nexpose/global_settings.rb +2 -3
- data/lib/nexpose/group.rb +25 -19
- data/lib/nexpose/json_serializer.rb +4 -14
- data/lib/nexpose/maint.rb +8 -9
- data/lib/nexpose/manage.rb +2 -2
- data/lib/nexpose/multi_tenant_user.rb +42 -42
- data/lib/nexpose/password_policy.rb +14 -14
- data/lib/nexpose/pool.rb +6 -5
- data/lib/nexpose/report.rb +30 -34
- data/lib/nexpose/report_template.rb +17 -18
- data/lib/nexpose/role.rb +64 -55
- data/lib/nexpose/scan.rb +77 -60
- data/lib/nexpose/scan_template.rb +17 -17
- data/lib/nexpose/scheduled_backup.rb +8 -8
- data/lib/nexpose/scheduled_maintenance.rb +9 -9
- data/lib/nexpose/shared_credential.rb +30 -33
- data/lib/nexpose/shared_secret.rb +5 -5
- data/lib/nexpose/silo.rb +68 -66
- data/lib/nexpose/silo_profile.rb +47 -50
- data/lib/nexpose/site.rb +101 -123
- data/lib/nexpose/site_credentials.rb +15 -17
- data/lib/nexpose/tag.rb +73 -80
- data/lib/nexpose/ticket.rb +45 -42
- data/lib/nexpose/user.rb +45 -45
- data/lib/nexpose/util.rb +1 -1
- data/lib/nexpose/version.rb +1 -1
- data/lib/nexpose/vuln.rb +45 -43
- data/lib/nexpose/vuln_def.rb +7 -7
- data/lib/nexpose/vuln_exception.rb +35 -36
- data/lib/nexpose/wait.rb +32 -28
- data/lib/nexpose/web_credentials.rb +34 -36
- metadata +2 -2
data/lib/nexpose/scan.rb
CHANGED
@@ -60,8 +60,8 @@ module Nexpose
|
|
60
60
|
#
|
61
61
|
def scan_devices_with_schedule(devices, schedules)
|
62
62
|
site_id = devices.map(&:site_id).uniq.first
|
63
|
-
xml
|
64
|
-
elem
|
63
|
+
xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id)
|
64
|
+
elem = REXML::Element.new('Devices')
|
65
65
|
devices.each do |device|
|
66
66
|
elem.add_element('device', 'id' => "#{device.id}")
|
67
67
|
end
|
@@ -107,7 +107,7 @@ module Nexpose
|
|
107
107
|
# @return [Scan] Scan launch information.
|
108
108
|
#
|
109
109
|
def scan_assets(site_id, assets)
|
110
|
-
xml
|
110
|
+
xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id)
|
111
111
|
hosts = REXML::Element.new('Hosts')
|
112
112
|
assets.each { |asset| _append_asset!(hosts, asset) }
|
113
113
|
xml.add_element(hosts)
|
@@ -129,7 +129,7 @@ module Nexpose
|
|
129
129
|
# @return [Status] whether the request was successful
|
130
130
|
#
|
131
131
|
def scan_assets_with_schedule(site_id, assets, schedules)
|
132
|
-
xml
|
132
|
+
xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id)
|
133
133
|
hosts = REXML::Element.new('Hosts')
|
134
134
|
assets.each { |asset| _append_asset!(hosts, asset) }
|
135
135
|
xml.add_element(hosts)
|
@@ -155,7 +155,7 @@ module Nexpose
|
|
155
155
|
# @return [Status] whether the request was successful
|
156
156
|
#
|
157
157
|
def scan_ips_with_schedule(site_id, ip_addresses, schedules)
|
158
|
-
xml
|
158
|
+
xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id)
|
159
159
|
hosts = REXML::Element.new('Hosts')
|
160
160
|
ip_addresses.each do |ip|
|
161
161
|
xml.add_element('range', 'from' => ip)
|
@@ -183,7 +183,7 @@ module Nexpose
|
|
183
183
|
# @return [Scan] Scan launch information.
|
184
184
|
#
|
185
185
|
def scan_ips(site_id, ip_addresses)
|
186
|
-
xml
|
186
|
+
xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id)
|
187
187
|
hosts = REXML::Element.new('Hosts')
|
188
188
|
ip_addresses.each do |ip|
|
189
189
|
xml.add_element('range', 'from' => ip)
|
@@ -199,7 +199,7 @@ module Nexpose
|
|
199
199
|
# @return [Scan] Scan launch information.
|
200
200
|
#
|
201
201
|
def scan_site(site_id)
|
202
|
-
xml
|
202
|
+
xml = make_xml('SiteScanRequest', 'site-id' => site_id)
|
203
203
|
response = execute(xml)
|
204
204
|
Scan.parse(response.res) if response.success
|
205
205
|
end
|
@@ -233,7 +233,7 @@ module Nexpose
|
|
233
233
|
def _append_asset!(xml, asset)
|
234
234
|
if asset.is_a? Nexpose::IPRange
|
235
235
|
xml.add_element('range', 'from' => asset.from, 'to' => asset.to)
|
236
|
-
else
|
236
|
+
else # Assume HostName
|
237
237
|
host = REXML::Element.new('host')
|
238
238
|
host.text = asset
|
239
239
|
xml.add_element(host)
|
@@ -368,8 +368,8 @@ module Nexpose
|
|
368
368
|
# recently completed first.
|
369
369
|
#
|
370
370
|
def past_scans(limit = nil)
|
371
|
-
uri
|
372
|
-
rows
|
371
|
+
uri = '/data/scan/global/scan-history'
|
372
|
+
rows = AJAX.row_pref_of(limit)
|
373
373
|
params = { 'sort' => 'endTime', 'dir' => 'DESC', 'startIndex' => 0 }
|
374
374
|
AJAX.preserving_preference(self, 'global-completed-scans') do
|
375
375
|
data = DataTable._get_json_table(self, uri, params, rows, limit)
|
@@ -386,15 +386,15 @@ module Nexpose
|
|
386
386
|
#
|
387
387
|
def paused_scans(site_id = nil, limit = nil)
|
388
388
|
if site_id
|
389
|
-
uri
|
390
|
-
rows
|
389
|
+
uri = "/data/scan/site/#{site_id}?status=active"
|
390
|
+
rows = AJAX.row_pref_of(limit)
|
391
391
|
params = { 'sort' => 'endTime', 'dir' => 'DESC', 'startIndex' => 0 }
|
392
392
|
AJAX.preserving_preference(self, 'site-active-scans') do
|
393
393
|
data = DataTable._get_json_table(self, uri, params, rows, limit).select { |scan| scan['paused'] }
|
394
394
|
data.map(&ActiveScan.method(:parse_json))
|
395
395
|
end
|
396
396
|
else
|
397
|
-
uri
|
397
|
+
uri = '/data/site/scans/dyntable.xml?printDocType=0&tableID=siteScansTable&activeOnly=true'
|
398
398
|
data = DataTable._get_dyn_table(self, uri).select { |scan| (scan['Status'].include? 'Paused') }
|
399
399
|
data.map(&ActiveScan.method(:parse_dyntable))
|
400
400
|
end
|
@@ -409,10 +409,9 @@ module Nexpose
|
|
409
409
|
# zip_file, if provided. Otherwise, returns raw ZIP binary data.
|
410
410
|
#
|
411
411
|
def export_scan(scan_id, zip_file = nil)
|
412
|
-
http
|
413
|
-
headers
|
414
|
-
|
415
|
-
resp = http.get("/data/scan/#{scan_id}/export", headers)
|
412
|
+
http = AJAX.https(self)
|
413
|
+
headers = { 'Cookie' => "nexposeCCSessionID=#{@session_id}", 'Accept-Encoding' => 'identity' }
|
414
|
+
resp = http.get("/data/scan/#{scan_id}/export", headers)
|
416
415
|
|
417
416
|
case resp
|
418
417
|
when Net::HTTPSuccess
|
@@ -502,7 +501,12 @@ module Nexpose
|
|
502
501
|
|
503
502
|
# Constructor
|
504
503
|
def initialize(scan_id, site_id, engine_id, status, start_time, end_time)
|
505
|
-
@scan_id
|
504
|
+
@scan_id = scan_id
|
505
|
+
@site_id = site_id
|
506
|
+
@engine_id = engine_id
|
507
|
+
@status = status
|
508
|
+
@start_time = start_time
|
509
|
+
@end_time = end_time
|
506
510
|
end
|
507
511
|
|
508
512
|
def self.parse(xml)
|
@@ -546,8 +550,16 @@ module Nexpose
|
|
546
550
|
|
547
551
|
# Constructor
|
548
552
|
def initialize(scan_id, site_id, engine_id, status, start_time, end_time, message, tasks, nodes, vulnerabilities)
|
549
|
-
@scan_id
|
550
|
-
@
|
553
|
+
@scan_id = scan_id
|
554
|
+
@site_id = site_id
|
555
|
+
@engine_id = engine_id
|
556
|
+
@status = status
|
557
|
+
@start_time = start_time
|
558
|
+
@end_time = end_time
|
559
|
+
@message = message
|
560
|
+
@tasks = tasks
|
561
|
+
@nodes = nodes
|
562
|
+
@vulnerabilities = vulnerabilities
|
551
563
|
end
|
552
564
|
|
553
565
|
# Parse a response from a Nexpose console into a valid ScanSummary object.
|
@@ -594,7 +606,9 @@ module Nexpose
|
|
594
606
|
attr_reader :pending, :active, :completed
|
595
607
|
|
596
608
|
def initialize(pending, active, completed)
|
597
|
-
@pending
|
609
|
+
@pending = pending
|
610
|
+
@active = active
|
611
|
+
@completed = completed
|
598
612
|
end
|
599
613
|
|
600
614
|
# Parse REXML to Tasks object.
|
@@ -616,7 +630,11 @@ module Nexpose
|
|
616
630
|
attr_reader :live, :dead, :filtered, :unresolved, :other
|
617
631
|
|
618
632
|
def initialize(live, dead, filtered, unresolved, other)
|
619
|
-
@live
|
633
|
+
@live = live
|
634
|
+
@dead = dead
|
635
|
+
@filtered = filtered
|
636
|
+
@unresolved = unresolved
|
637
|
+
@other = other
|
620
638
|
end
|
621
639
|
|
622
640
|
# Parse REXML to Nodes object.
|
@@ -637,19 +655,17 @@ module Nexpose
|
|
637
655
|
# Value class for tracking vulnerability counts.
|
638
656
|
#
|
639
657
|
class Vulnerabilities
|
640
|
-
attr_reader :vuln_exploit, :vuln_version, :vuln_potential,
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
@
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
not_vuln_exploit, not_vuln_version,
|
652
|
-
error, disabled, other
|
658
|
+
attr_reader :vuln_exploit, :vuln_version, :vuln_potential, :not_vuln_exploit, :not_vuln_version, :error, :disabled, :other
|
659
|
+
|
660
|
+
def initialize(vuln_exploit, vuln_version, vuln_potential, not_vuln_exploit, not_vuln_version, error, disabled, other)
|
661
|
+
@vuln_exploit = vuln_exploit
|
662
|
+
@vuln_version = vuln_version
|
663
|
+
@vuln_potential = vuln_potential
|
664
|
+
@not_vuln_exploit = not_vuln_exploit
|
665
|
+
@not_vuln_version = not_vuln_version
|
666
|
+
@error = error
|
667
|
+
@disabled = disabled
|
668
|
+
@other = other
|
653
669
|
end
|
654
670
|
|
655
671
|
# Parse REXML to Vulnerabilities object.
|
@@ -691,11 +707,11 @@ module Nexpose
|
|
691
707
|
def initialize(severity = nil, count = 0)
|
692
708
|
if severity
|
693
709
|
@severities = {}
|
694
|
-
@count
|
710
|
+
@count = 0
|
695
711
|
add_severity(severity.to_i, count)
|
696
712
|
else
|
697
713
|
@severities = nil
|
698
|
-
@count
|
714
|
+
@count = count
|
699
715
|
end
|
700
716
|
end
|
701
717
|
|
@@ -718,7 +734,8 @@ module Nexpose
|
|
718
734
|
attr_reader :engine
|
719
735
|
|
720
736
|
def initialize(scan_id, engine_id)
|
721
|
-
@id
|
737
|
+
@id = scan_id
|
738
|
+
@engine = engine_id
|
722
739
|
end
|
723
740
|
|
724
741
|
def self.parse(xml)
|
@@ -781,18 +798,18 @@ module Nexpose
|
|
781
798
|
# object.
|
782
799
|
def self.parse_json(json)
|
783
800
|
new do
|
784
|
-
@id
|
785
|
-
@site_id
|
786
|
-
@status
|
787
|
-
@start_time
|
788
|
-
@end_time
|
789
|
-
@duration
|
790
|
-
@vulns
|
791
|
-
@assets
|
792
|
-
@risk_score
|
793
|
-
@type
|
801
|
+
@id = json['scanID']
|
802
|
+
@site_id = json['siteID']
|
803
|
+
@status = CompletedScan._parse_status(json['status'])
|
804
|
+
@start_time = Time.at(json['startTime'] / 1000)
|
805
|
+
@end_time = Time.at(json['endTime'] / 1000)
|
806
|
+
@duration = json['duration']
|
807
|
+
@vulns = json['vulnerabilityCount']
|
808
|
+
@assets = json['liveHosts']
|
809
|
+
@risk_score = json['riskScore']
|
810
|
+
@type = json['startedByCD'] == 'S' ? :scheduled : :manual
|
794
811
|
@engine_name = json['scanEngineName']
|
795
|
-
@scan_name
|
812
|
+
@scan_name = json['scanName']
|
796
813
|
end
|
797
814
|
end
|
798
815
|
|
@@ -814,18 +831,18 @@ module Nexpose
|
|
814
831
|
class ActiveScan < CompletedScan
|
815
832
|
def self.parse_dyntable(json)
|
816
833
|
new do
|
817
|
-
@id
|
818
|
-
@site_id
|
819
|
-
@status
|
820
|
-
@start_time
|
821
|
-
@end_time
|
822
|
-
@duration
|
823
|
-
@vulns
|
824
|
-
@assets
|
825
|
-
@risk_score
|
826
|
-
@type
|
834
|
+
@id = json['Scan ID']
|
835
|
+
@site_id = json['Site ID']
|
836
|
+
@status = CompletedScan._parse_status(json['Status Code'])
|
837
|
+
@start_time = Time.at(json['Started'].to_i / 1000)
|
838
|
+
@end_time = Time.at(json['Progress'].to_i / 1000)
|
839
|
+
@duration = json['Elapsed'].to_i
|
840
|
+
@vulns = json['Vulnerabilities Discovered'].to_i
|
841
|
+
@assets = json['Devices Discovered'].to_i
|
842
|
+
@risk_score = json['riskScore']
|
843
|
+
@type = json['Scan Type'] == 'Manual' ? :manual : :scheduled
|
827
844
|
@engine_name = json['Scan Engine']
|
828
|
-
@scan_name
|
845
|
+
@scan_name = json['Scan Name']
|
829
846
|
end
|
830
847
|
end
|
831
848
|
|
@@ -11,7 +11,7 @@ module Nexpose
|
|
11
11
|
templates['resources'].map { |t| ScanTemplateSummary.new(t) }
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
alias scan_templates list_scan_templates
|
15
15
|
|
16
16
|
# Delete a scan template from the console.
|
17
17
|
# Cannot be used to delete a built-in template.
|
@@ -31,7 +31,7 @@ module Nexpose
|
|
31
31
|
|
32
32
|
def initialize(json)
|
33
33
|
@name = json['name']
|
34
|
-
@id
|
34
|
+
@id = json['id']
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -110,7 +110,7 @@ module Nexpose
|
|
110
110
|
# @return [Boolean] Whether control scanning in enabled.
|
111
111
|
def control_scanning?
|
112
112
|
global_controls_scan = REXML::XPath.first(@xml, 'ScanTemplate/ControlsScan/globalControlsScanEnabled')
|
113
|
-
local_controls_scan
|
113
|
+
local_controls_scan = REXML::XPath.first(@xml, 'ScanTemplate/ControlsScan/localControlsScanEnabled')
|
114
114
|
|
115
115
|
global_controls_scan.attributes['enabled'] == '1' || local_controls_scan.attributes['enabled'] == '1'
|
116
116
|
end
|
@@ -237,31 +237,31 @@ module Nexpose
|
|
237
237
|
# @param [Array] ports Ports to scan for TCP service discovery
|
238
238
|
def tcp_service_discovery_ports=(ports)
|
239
239
|
service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/TCPPortScan')
|
240
|
-
service_ports.attributes['mode'] =
|
241
|
-
service_ports.attributes['method'] =
|
242
|
-
REXML::XPath.first(service_ports, './portList').text = ports.join(
|
240
|
+
service_ports.attributes['mode'] = 'custom'
|
241
|
+
service_ports.attributes['method'] = 'syn'
|
242
|
+
REXML::XPath.first(service_ports, './portList').text = ports.join(',')
|
243
243
|
end
|
244
244
|
|
245
245
|
# Exclude TCP ports during TCP service discovery
|
246
246
|
# @param [Array] ports TCP ports to exclude from TCP service discovery
|
247
247
|
def exclude_tcp_service_discovery_ports=(ports)
|
248
248
|
service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/ExcludedTCPPortScan')
|
249
|
-
REXML::XPath.first(service_ports, './portList').text = ports.join(
|
249
|
+
REXML::XPath.first(service_ports, './portList').text = ports.join(',')
|
250
250
|
end
|
251
251
|
|
252
252
|
# Set custom UDP ports to scan for UDP service discovery
|
253
253
|
# @param [Array] ports Ports to scan during UDP service discovery
|
254
254
|
def udp_service_discovery_ports=(ports)
|
255
255
|
service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/UDPPortScan')
|
256
|
-
service_ports.attributes['mode'] =
|
257
|
-
REXML::XPath.first(service_ports, './portList').text = ports.join(
|
256
|
+
service_ports.attributes['mode'] = 'custom'
|
257
|
+
REXML::XPath.first(service_ports, './portList').text = ports.join(',')
|
258
258
|
end
|
259
259
|
|
260
260
|
# Exclude UDP ports when performing UDP service discovery
|
261
261
|
# @param [Array] ports UDP ports to exclude from UDP service discovery
|
262
262
|
def exclude_udp_service_discovery_ports=(ports)
|
263
263
|
service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/ExcludedUDPPortScan')
|
264
|
-
REXML::XPath.first(service_ports, './portList').text = ports.join(
|
264
|
+
REXML::XPath.first(service_ports, './portList').text = ports.join(',')
|
265
265
|
end
|
266
266
|
|
267
267
|
# Enable or disable UDP service discovery
|
@@ -509,7 +509,7 @@ module Nexpose
|
|
509
509
|
#
|
510
510
|
def self.copy(nsc, id)
|
511
511
|
dupe = load(nsc, id)
|
512
|
-
dupe.id
|
512
|
+
dupe.id = '#NewScanTemplate#'
|
513
513
|
dupe.name = "#{dupe.name} Copy"
|
514
514
|
dupe
|
515
515
|
end
|
@@ -532,14 +532,14 @@ module Nexpose
|
|
532
532
|
return if level.nil?
|
533
533
|
return unless ['full', 'default', 'none'].include? level.downcase
|
534
534
|
logging = REXML::XPath.first(@xml, 'ScanTemplate/Logging')
|
535
|
-
if
|
535
|
+
if logging.nil?
|
536
536
|
logging = REXML::Element.new('Logging')
|
537
537
|
@xml.add_element(logging)
|
538
538
|
end
|
539
539
|
aces = REXML::XPath.first(logging, 'aces')
|
540
|
-
if
|
541
|
-
|
542
|
-
|
540
|
+
if aces.nil?
|
541
|
+
aces = REXML::Element.new('aces')
|
542
|
+
logging.add_element(aces)
|
543
543
|
end
|
544
544
|
aces.attributes['level'] = level
|
545
545
|
end
|
@@ -551,13 +551,13 @@ module Nexpose
|
|
551
551
|
return 'default' if logging.nil?
|
552
552
|
aces = REXML::XPath.first(logging, 'aces')
|
553
553
|
return 'default' if aces.nil?
|
554
|
-
|
554
|
+
aces.attributes['level']
|
555
555
|
end
|
556
556
|
|
557
557
|
# @return [Boolean] whether asset configuration scanning is enabled for
|
558
558
|
# this template.
|
559
559
|
def aces_enabled?
|
560
|
-
|
560
|
+
aces_level == 'full'
|
561
561
|
end
|
562
562
|
|
563
563
|
# Enable or disable the debug logging.
|
@@ -22,14 +22,14 @@ module Nexpose
|
|
22
22
|
attr_accessor :cancellation_window
|
23
23
|
|
24
24
|
def initialize(start:, enabled: true, type:, interval:, platform_independent: true, description: nil, pause_local_scans: true, cancellation_window: 0)
|
25
|
-
@schedule_start
|
26
|
-
@enabled
|
27
|
-
@schedule_type
|
28
|
-
@schedule_interval
|
25
|
+
@schedule_start = start
|
26
|
+
@enabled = enabled
|
27
|
+
@schedule_type = type
|
28
|
+
@schedule_interval = interval.to_i
|
29
29
|
@platform_independent = platform_independent
|
30
|
-
@description
|
31
|
-
@pause_local_scans
|
32
|
-
@cancellation_window
|
30
|
+
@description = description
|
31
|
+
@pause_local_scans = pause_local_scans
|
32
|
+
@cancellation_window = cancellation_window.to_i
|
33
33
|
end
|
34
34
|
|
35
35
|
def to_json
|
@@ -72,7 +72,7 @@ module Nexpose
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def self.load(nsc)
|
75
|
-
uri
|
75
|
+
uri = '/api/2.1/schedule_backup/'
|
76
76
|
resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON)
|
77
77
|
hash = JSON.parse(resp, symbolize_names: true).first
|
78
78
|
Nexpose::ScheduledBackup.from_hash(hash || [])
|
@@ -24,14 +24,14 @@ module Nexpose
|
|
24
24
|
attr_accessor :cancellation_window
|
25
25
|
|
26
26
|
def initialize(start:, enabled: true, type:, interval:, reindex: false, compress: true, cleanup: true, pause_local_scans: true, cancellation_window: 0)
|
27
|
-
@schedule_start
|
28
|
-
@enabled
|
29
|
-
@schedule_type
|
30
|
-
@schedule_interval
|
31
|
-
@reindex
|
32
|
-
@compress
|
33
|
-
@cleanup
|
34
|
-
@pause_local_scans
|
27
|
+
@schedule_start = start
|
28
|
+
@enabled = enabled
|
29
|
+
@schedule_type = type
|
30
|
+
@schedule_interval = interval.to_i
|
31
|
+
@reindex = reindex
|
32
|
+
@compress = compress
|
33
|
+
@cleanup = cleanup
|
34
|
+
@pause_local_scans = pause_local_scans
|
35
35
|
@cancellation_window = cancellation_window.to_i
|
36
36
|
end
|
37
37
|
|
@@ -77,7 +77,7 @@ module Nexpose
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def self.load(nsc)
|
80
|
-
uri
|
80
|
+
uri = '/api/2.1/schedule_maintenance/'
|
81
81
|
resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON)
|
82
82
|
hash = JSON.parse(resp, symbolize_names: true).first
|
83
83
|
Nexpose::ScheduledMaintenance.from_hash(hash || [])
|
@@ -4,21 +4,21 @@ module Nexpose
|
|
4
4
|
|
5
5
|
def list_shared_credentials
|
6
6
|
creds = DataTable._get_json_table(self,
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
'/data/credential/shared/listing',
|
8
|
+
{ 'sort' => -1,
|
9
|
+
'table-id' => 'credential-listing' })
|
10
10
|
creds.map { |c| SharedCredentialSummary.from_json(c) }
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
alias list_shared_creds list_shared_credentials
|
14
|
+
alias shared_credentials list_shared_credentials
|
15
|
+
alias shared_creds list_shared_credentials
|
16
16
|
|
17
17
|
def delete_shared_credential(id)
|
18
18
|
AJAX.post(self, "/data/credential/shared/delete?credid=#{id}")
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
alias delete_shared_cred delete_shared_credential
|
22
22
|
end
|
23
23
|
|
24
24
|
class SharedCredentialSummary < Credential
|
@@ -29,18 +29,18 @@ module Nexpose
|
|
29
29
|
attr_accessor :name
|
30
30
|
# The credential service/type. See Nexpose::Credential::Service.
|
31
31
|
attr_accessor :service
|
32
|
-
alias
|
33
|
-
alias
|
32
|
+
alias type service
|
33
|
+
alias type= service=
|
34
34
|
# Domain or realm.
|
35
35
|
attr_accessor :domain
|
36
36
|
# User name.
|
37
37
|
attr_accessor :username
|
38
|
-
alias
|
39
|
-
alias
|
38
|
+
alias user_name username
|
39
|
+
alias user_name= username=
|
40
40
|
# User name to use when elevating permissions (e.g., sudo).
|
41
41
|
attr_accessor :privilege_username
|
42
|
-
alias
|
43
|
-
alias
|
42
|
+
alias permission_elevation_user privilege_username
|
43
|
+
alias permission_elevation_user= privilege_username=
|
44
44
|
# Boolean to indicate whether this credential applies to all sites.
|
45
45
|
attr_accessor :all_sites
|
46
46
|
# When this credential was last modified.
|
@@ -48,14 +48,14 @@ module Nexpose
|
|
48
48
|
|
49
49
|
def self.from_json(json)
|
50
50
|
cred = new
|
51
|
-
cred.id
|
52
|
-
cred.name
|
53
|
-
cred.type
|
54
|
-
cred.domain
|
55
|
-
cred.username
|
51
|
+
cred.id = json['credentialID']['ID']
|
52
|
+
cred.name = json['name']
|
53
|
+
cred.type = json['service']
|
54
|
+
cred.domain = json['domain']
|
55
|
+
cred.username = json['username']
|
56
56
|
cred.privilege_username = json['privilegeElevationUsername']
|
57
|
-
cred.all_sites
|
58
|
-
cred.last_modified
|
57
|
+
cred.all_sites = json['scope'] == 'ALL_SITES_ENABLED_DEFAULT'
|
58
|
+
cred.last_modified = Time.at(json['lastModified']['time'] / 1000)
|
59
59
|
cred
|
60
60
|
end
|
61
61
|
|
@@ -83,12 +83,12 @@ module Nexpose
|
|
83
83
|
attr_accessor :pem_key
|
84
84
|
# Password to use when elevating permissions (e.g., sudo).
|
85
85
|
attr_accessor :privilege_password
|
86
|
-
alias
|
87
|
-
alias
|
86
|
+
alias permission_elevation_password privilege_password
|
87
|
+
alias permission_elevation_password= privilege_password=
|
88
88
|
# Permission elevation type. See Nexpose::Credential::ElevationType.
|
89
89
|
attr_accessor :privilege_type
|
90
|
-
alias
|
91
|
-
alias
|
90
|
+
alias permission_elevation_type privilege_type
|
91
|
+
alias permission_elevation_type= privilege_type=
|
92
92
|
# Privacty password of SNMP v3 credential
|
93
93
|
attr_accessor :privacy_password
|
94
94
|
# Authentication type of SNMP v3 credential
|
@@ -130,17 +130,14 @@ module Nexpose
|
|
130
130
|
def as_xml
|
131
131
|
xml = REXML::Element.new('Credential')
|
132
132
|
xml.add_attribute('id', @id)
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
desc = xml.add_element('Description').add_text(@description)
|
133
|
+
xml.add_element('Name').add_text(@name)
|
134
|
+
xml.add_element('Description').add_text(@description)
|
137
135
|
|
138
136
|
services = xml.add_element('Services')
|
139
|
-
|
137
|
+
services.add_element('Service').add_attribute('type', @service)
|
140
138
|
|
141
139
|
(account = xml.add_element('Account')).add_attribute('type', 'nexpose')
|
142
140
|
account.add_element('Field', { 'name' => 'database' }).add_text(@database)
|
143
|
-
|
144
141
|
account.add_element('Field', { 'name' => 'domain' }).add_text(@domain)
|
145
142
|
account.add_element('Field', { 'name' => 'username' }).add_text(@username)
|
146
143
|
account.add_element('Field', { 'name' => 'ntlmhash' }).add_text(@ntlm_hash) if @ntlm_hash
|
@@ -188,10 +185,10 @@ module Nexpose
|
|
188
185
|
unless engine_id
|
189
186
|
engine_id = nsc.engines.detect { |e| e.name == 'Local scan engine' }.id
|
190
187
|
end
|
191
|
-
@port
|
188
|
+
@port = Credential::DEFAULT_PORTS[@service] if @port.nil?
|
192
189
|
parameters = _to_param(target, engine_id, @port, siteid)
|
193
|
-
xml
|
194
|
-
result
|
190
|
+
xml = AJAX.form_post(nsc, '/data/credential/shared/test', parameters)
|
191
|
+
result = REXML::XPath.first(REXML::Document.new(xml), 'TestAdminCredentialsResult')
|
195
192
|
result.attributes['success'].to_i == 1
|
196
193
|
end
|
197
194
|
|