nexpose 0.8.8 → 0.8.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0895452fa39e68f031ad27edc40a94cef8337730
4
- data.tar.gz: 051981f1f5ef5a0e04977c3a7f5bc1447b2cee3c
3
+ metadata.gz: 6698a2821faefa7c1822f324cc1bfd355869ad7f
4
+ data.tar.gz: 3a14efb354cbc7036cf829f60088ceeaa0f7a80b
5
5
  SHA512:
6
- metadata.gz: 9ebb703fbacc51a22fc0d60e18b1ac063fe853406b22c6ee2b7b3d77b0f9feda1e2441f07d0cb8b5dfeb8cb96937451cc94a5088e24485a34a7e078a98d37187
7
- data.tar.gz: 4f7c7f467df77177e2762f5bf927548fe67e70c641855e7108a0219e1761bb9f1996664862edaaeb2a017ebd3df252bccfaf71163ba80053a9147dd609b030b9
6
+ metadata.gz: 219848942e56f658d1a3f43e8411ded2c12e693d5f258106196ddca5121c3434be50c17dffd45fe61504d5d76050bd77c123ea3d844e5f07a65656a353b03ea2
7
+ data.tar.gz: 89ae18299c87ef71a2805038ef3f1e3c7ab7a53cf87e0c66f799dbaa83e024f7714dc4198854d509156646472aea80d344f215c2de7b4fcfa6d71535ca87ef97
@@ -72,6 +72,7 @@ require 'nexpose/discovery'
72
72
  require 'nexpose/discovery/filter'
73
73
  require 'nexpose/engine'
74
74
  require 'nexpose/filter'
75
+ require 'nexpose/global_settings'
75
76
  require 'nexpose/group'
76
77
  require 'nexpose/dag'
77
78
  require 'nexpose/manage'
@@ -0,0 +1,117 @@
1
+ module Nexpose
2
+ # Object used to manage the global settings of a Nexpose console.
3
+ #
4
+ class GlobalSettings
5
+ # IP addresses and/or host names that will be excluded from scanning across
6
+ # all sites.
7
+ attr_accessor :asset_exclusions
8
+
9
+ # Whether control scanning in enabled. A feature tied to ControlsInsight
10
+ # integration.
11
+ attr_accessor :control_scanning
12
+
13
+ # XML document representing the entire configuration.
14
+ attr_reader :xml
15
+
16
+ # Private constructor. See #load method for retrieving a settings object.
17
+ #
18
+ def initialize(xml)
19
+ @xml = xml
20
+
21
+ @asset_exclusions = HostOrIP.parse(xml)
22
+ @control_scanning = _get_control_scanning(xml)
23
+ end
24
+
25
+ # Returns true if controls scanning is enabled.
26
+ def control_scanning?
27
+ control_scanning
28
+ end
29
+
30
+ # Save any updates to this settings object to the Nexpose console.
31
+ #
32
+ # @param [Connection] nsc Connection to a Nexpose console.
33
+ # @return [Boolean] Whether saving was successful.
34
+ #
35
+ def save(nsc)
36
+ # load method can return XML missing this required attribute.
37
+ unless REXML::XPath.first(xml, '//*[@recalculation_duration]')
38
+ risk_model = REXML::XPath.first(xml, '//riskModel')
39
+ risk_model.add_attribute('recalculation_duration', 'do_not_recalculate')
40
+ end
41
+
42
+ _replace_exclusions(xml, asset_exclusions)
43
+ _set_control_scanning(xml, control_scanning)
44
+
45
+ response = AJAX.post(nsc, '/data/admin/global-settings', xml)
46
+ XMLUtils.success? response
47
+ end
48
+
49
+ # Add an asset exclusion setting.
50
+ #
51
+ # @param [IPRange|HostName|String] host_or_ip Host or IP (range) to exclude
52
+ # from scanning by the Nexpose console.
53
+ #
54
+ def add_exclusion(host_or_ip)
55
+ asset = host_or_ip
56
+ unless host_or_ip.respond_to?(:host) || host_or_ip.respond_to?(:from)
57
+ asset = HostOrIP.convert(host_or_ip)
58
+ end
59
+ @asset_exclusions << asset
60
+ end
61
+
62
+ # Remove an asset exclusion setting.
63
+ # If you need to remove a range of IPs, be sure to explicitly supply an
64
+ # IPRange object to the method.
65
+ #
66
+ # @param [IPRange|HostName|String] host_or_ip Host or IP (range) to remove
67
+ # from the exclusion list.
68
+ #
69
+ def remove_exclusion(host_or_ip)
70
+ asset = host_or_ip
71
+ unless host_or_ip.respond_to?(:host) || host_or_ip.respond_to?(:from)
72
+ # Attept to convert String to appropriate object.
73
+ asset = HostOrIP.convert(host_or_ip)
74
+ end
75
+ @asset_exclusions = asset_exclusions.reject { |a| a.eql? asset }
76
+ end
77
+
78
+ # Load the global settings from a Nexpose console.
79
+ #
80
+ # @param [Connection] nsc Connection to a Nexpose console.
81
+ # @return [GlobalSettings] Settings object for the console.
82
+ #
83
+ def self.load(nsc)
84
+ response = AJAX.get(nsc, '/data/admin/global-settings')
85
+ new(REXML::Document.new(response))
86
+ end
87
+
88
+ # Internal method for updating exclusions before saving.
89
+ def _replace_exclusions(xml, exclusions)
90
+ xml.elements.delete('//ExcludedHosts')
91
+ elem = xml.root.add_element('ExcludedHosts')
92
+ exclusions.each do |exclusion|
93
+ elem.add_element(exclusion.as_xml)
94
+ end
95
+ end
96
+
97
+ # Internal method for parsing XML for whether control scanning in enabled.
98
+ def _get_control_scanning(xml)
99
+ enabled = false
100
+ if elem = REXML::XPath.first(xml, '//enableControlsScan[@enabled]')
101
+ enabled = elem.attribute('enabled').value.to_i == 1
102
+ end
103
+ enabled
104
+ end
105
+
106
+ # Internal method for updating control scanning before saving.
107
+ def _set_control_scanning(xml, enabled)
108
+ if elem = REXML::XPath.first(xml, '//enableControlsScan')
109
+ elem.attributes['enabled'] = enabled ? '1' : '0'
110
+ else
111
+ elem = REXML::Element.new('ControlsScan', xml.root)
112
+ elem.add_element('enableControlsScan',
113
+ 'enabled' => enabled ? '1' : '0')
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,14 @@
1
+ <GlobalSettings>
2
+ <riskModel id="real_risk" recalculation_duration="do_not_recalculate"></riskModel>
3
+ <RiskConfig includeRiskModifiers="false">
4
+ <RiskModifiers veryHigh="2" high="1.5" medium="1" low="0.75" veryLow="0.5"></RiskModifiers>
5
+ </RiskConfig>
6
+ <ControlsScan>
7
+ <enableControlsScan enabled="0"></enableControlsScan>
8
+ </ControlsScan>
9
+ <ExcludedHosts>
10
+ <range from="10.4.18.219"></range>
11
+ <range from="10.4.25.117"></range>
12
+ </ExcludedHosts>
13
+ </GlobalSettings>
14
+
@@ -217,17 +217,8 @@ module Nexpose
217
217
  # @param [String] asset Identifier of an asset, either IP or host name.
218
218
  #
219
219
  def add_asset(asset)
220
- begin
221
- # If the asset registers as a valid IP, store as IP.
222
- ip = IPAddr.new(asset)
223
- add_ip(asset)
224
- rescue ArgumentError => e
225
- if e.message == 'invalid address'
226
- add_host(asset)
227
- else
228
- raise "Unable to parse asset: '#{asset}'. #{e.message}"
229
- end
230
- end
220
+ obj = HostOrIP.convert(asset)
221
+ @assets << obj
231
222
  end
232
223
 
233
224
  # Remove an asset to this site, resolving whether an IP or hostname is
@@ -34,5 +34,62 @@ module Nexpose
34
34
 
35
35
  xml
36
36
  end
37
+
38
+ # Check a typical Nexpose XML response for success.
39
+ # Typically, the root element has a 'success' attribute, and its value is
40
+ # '1' if the call succeeded.
41
+ #
42
+ def self.success?(xml_string)
43
+ xml = ::REXML::Document.new(xml_string.to_s)
44
+ success = ::REXML::XPath.first(xml, '//@success')
45
+ !success.nil? && success.value.to_i == 1
46
+ end
47
+ end
48
+
49
+ # Function module for dealing with String to HostName|IPRange conversions.
50
+ #
51
+ module HostOrIP
52
+ module_function
53
+
54
+ # Convert a host or IP address to the corresponding HostName or IPRange
55
+ # class.
56
+ #
57
+ # If the String cannot be converted, it will raise an error.
58
+ #
59
+ # @param [String] asset String representation of an IP or host name.
60
+ # @return [IPRange|HostName] Valid class, if it can be converted.
61
+ #
62
+ def convert(asset)
63
+ begin
64
+ # Use IPAddr construtor validation to see if it's an IP.
65
+ IPAddr.new(asset)
66
+ IPRange.new(asset)
67
+ rescue ArgumentError => e
68
+ if e.message == 'invalid address'
69
+ HostName.new(asset)
70
+ else
71
+ raise "Unable to parse asset: '#{asset}'. #{e.message}"
72
+ end
73
+ end
74
+ end
75
+
76
+ # Parse a REXML::Document or REXML::Element for any hosts listed and convert
77
+ # them to HostName and IPRange objects.
78
+ #
79
+ # @param [REXML::Document|REXML::Element] xml REXML class potentially
80
+ # containing host references.
81
+ # @return [Array[HostName|IPRange]] Collection of parsed hosts.
82
+ #
83
+ def parse(xml)
84
+ coll = []
85
+ xml.elements.each('//range') do |elem|
86
+ to = elem.attribute('to').nil? ? nil : elem.attribute('to').value
87
+ coll << IPRange.new(elem.attribute('from').value, to)
88
+ end
89
+ xml.elements.each('//host') do |elem|
90
+ coll << HostName.new(elem.text)
91
+ end
92
+ coll
93
+ end
37
94
  end
38
95
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nexpose
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.8
4
+ version: 0.8.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - HD Moore
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-10-17 00:00:00.000000000 Z
14
+ date: 2014-10-20 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rex
@@ -85,6 +85,7 @@ files:
85
85
  - lib/nexpose/engine.rb
86
86
  - lib/nexpose/error.rb
87
87
  - lib/nexpose/filter.rb
88
+ - lib/nexpose/global_settings.rb
88
89
  - lib/nexpose/group.rb
89
90
  - lib/nexpose/maint.rb
90
91
  - lib/nexpose/manage.rb
@@ -95,6 +96,7 @@ files:
95
96
  - lib/nexpose/role.rb
96
97
  - lib/nexpose/scan.rb
97
98
  - lib/nexpose/scan_template.rb
99
+ - lib/nexpose/settings.xml
98
100
  - lib/nexpose/shared_cred.rb
99
101
  - lib/nexpose/silo.rb
100
102
  - lib/nexpose/silo_profile.rb