nexpose 0.8.18 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24b07c5aa9671577da0a19a249babd2c0fce5ff6
4
- data.tar.gz: 30f364953ab62ff807f82deffb848b2ceef80636
3
+ metadata.gz: b26ec57d92c374454b5be75b30201eddfcf23e99
4
+ data.tar.gz: 621fad61669205dbf85052ee210019f00578fb50
5
5
  SHA512:
6
- metadata.gz: fca1a54493ded6d695c2668c53c3ced413c7c82b181367bf3af666cf9cab10ad7209c1a7e6a67f059e6ba7b03f03ba5a783d9aa7ed0706754e7413e847e89d20
7
- data.tar.gz: 9f30a2887a5b7f7064b1bf8c5dd7482e7762cb0b7b25e5d91a22dadab2e6577590bc374f76323372394bda48db48526a4663058ae7a356a8148bcec10f1e6764
6
+ metadata.gz: 27b3f31b2baa7db3637a65f5b9c2bfbdf9af2f8f0918ad7cf1af724c285a219b9e4e0faaf85a8a89b51c8a53ab079327f7d6029decf39dda1e489852271edd5a
7
+ data.tar.gz: 1fd837247c8a92f57d138712d8e7de1585f695353dc75fdaa14b16d5aac9ce4720dbbb480911867f6e2cede17dec9b3460621dd0d84bff06063669894b28b9de
@@ -66,8 +66,9 @@ require 'nexpose/api'
66
66
  require 'nexpose/api_request'
67
67
  require 'nexpose/common'
68
68
  require 'nexpose/console'
69
- require 'nexpose/creds'
70
- require 'nexpose/shared_cred'
69
+ require 'nexpose/credential'
70
+ require 'nexpose/site_credential'
71
+ require 'nexpose/shared_credential'
71
72
  require 'nexpose/data_table'
72
73
  require 'nexpose/device'
73
74
  require 'nexpose/discovery'
@@ -156,6 +156,8 @@ module Nexpose
156
156
  response.body
157
157
  when Net::HTTPCreated
158
158
  response.body
159
+ when Net::HTTPForbidden
160
+ raise Nexpose::PermissionError.new(response)
159
161
  when Net::HTTPUnauthorized
160
162
  raise Nexpose::PermissionError.new(response)
161
163
  else
@@ -25,12 +25,13 @@ module Nexpose
25
25
  next if k == :url # Do not store self-referential URL.
26
26
  # Store resource URLs separately and create lazy accessors.
27
27
  if v.is_a?(Hash) && v.key?(:url)
28
- instance_variable_set("@#{k}_url", v[:url].gsub(/.*\/api/, '/api'))
29
- self.class.send(:define_method, k, proc { |conn = nsc| load_resource(conn, k, instance_variable_get("@#{k}_url")) })
28
+ self.class.send(:define_method, k, proc { |conn = nsc| load_resource(conn, k, v[:url].gsub(/.*\/api/, '/api')) })
30
29
  else
31
30
  # Convert timestamps.
32
31
  if v.is_a?(String) && v.match(/^\d{8}T\d{6}\.\d{3}/)
33
32
  instance_variable_set("@#{k}", ISO8601.to_time(v))
33
+ elsif v.is_a?(Array) && k == :attributes
34
+ instance_variable_set("@#{k}", v.map { |h| { h[:key] => h[:value] } })
34
35
  else
35
36
  instance_variable_set("@#{k}", v)
36
37
  end
@@ -54,7 +55,13 @@ module Nexpose
54
55
  obj = class_from_string(k)
55
56
  resp = AJAX.get(nsc, url, AJAX::CONTENT_TYPE::JSON)
56
57
  hash = JSON.parse(resp, symbolize_names: true)
57
- resources = hash[:resources].map { |e| obj.method(:new).call.object_from_hash(nsc, e) }
58
+ if hash.is_a?(Array)
59
+ resources = hash.map { |e| obj.method(:new).call.object_from_hash(nsc, e) }
60
+ elsif hash.key?(:resources)
61
+ resources = hash[:resources].map { |e| obj.method(:new).call.object_from_hash(nsc, e) }
62
+ else
63
+ resources = obj.method(:new).call.object_from_hash(nsc, hash)
64
+ end
58
65
  instance_variable_set("@#{k}", resources)
59
66
  self.class.send(:define_method, k, proc { instance_variable_get("@#{k}") })
60
67
  resources
@@ -70,6 +77,7 @@ module Nexpose
70
77
  #
71
78
  def class_from_string(field)
72
79
  str = field.to_s.split('_').map(&:capitalize!).join
80
+ str = 'Vulnerability' if str == 'Vulnerabilities'
73
81
  str.chop! if str.end_with?('s')
74
82
  Object.const_get('Nexpose').const_get(str)
75
83
  end
@@ -47,34 +47,45 @@ module Nexpose
47
47
  @http.read_timeout = options[:timeout] if options.key? :timeout
48
48
  @raw_response = @http.post(@uri.path, @req, @headers)
49
49
  @raw_response_data = @raw_response.read_body
50
- @res = parse_xml(@raw_response_data)
51
50
 
52
- unless @res.root
53
- @error = 'Nexpose service returned invalid XML.'
54
- return @sid
55
- end
51
+ # Allow the :raw keyword to bypass XML parsing.
52
+ if options[:raw]
53
+ if raw_response_data =~ /success="1"/
54
+ @success = true
55
+ else
56
+ @success = false
57
+ @error = "User requested raw XML response. Not parsing failures."
58
+ end
59
+ else
60
+ @res = parse_xml(@raw_response_data)
56
61
 
57
- @sid = attributes['session-id']
62
+ unless @res.root
63
+ @error = 'Nexpose service returned invalid XML.'
64
+ return @sid
65
+ end
58
66
 
59
- if (attributes['success'] and attributes['success'].to_i == 1)
60
- @success = true
61
- elsif @api_version =~ /1.2/ and @res and (@res.get_elements '//Exception').count < 1
62
- @success = true
63
- else
64
- @success = false
65
- if @api_version =~ /1.2/
66
- @res.elements.each('//Exception/Message') do |message|
67
+ @sid = attributes['session-id']
68
+
69
+ if (attributes['success'] and attributes['success'].to_i == 1)
70
+ @success = true
71
+ elsif @api_version =~ /1.2/ and @res and (@res.get_elements '//Exception').count < 1
72
+ @success = true
73
+ else
74
+ @success = false
75
+ if @api_version =~ /1.2/
76
+ @res.elements.each('//Exception/Message') do |message|
67
77
  @error = message.text.sub(/.*Exception: */, '')
68
- end
78
+ end
69
79
  @res.elements.each('//Exception/Stacktrace') do |stacktrace|
70
80
  @trace = stacktrace.text
71
81
  end
72
- else
73
- @res.elements.each('//message') do |message|
74
- @error = message.text.sub(/.*Exception: */, '')
75
- end
76
- @res.elements.each('//stacktrace') do |stacktrace|
77
- @trace = stacktrace.text
82
+ else
83
+ @res.elements.each('//message') do |message|
84
+ @error = message.text.sub(/.*Exception: */, '')
85
+ end
86
+ @res.elements.each('//stacktrace') do |stacktrace|
87
+ @trace = stacktrace.text
88
+ end
78
89
  end
79
90
  end
80
91
  end
@@ -108,7 +108,7 @@ module Nexpose
108
108
  resp = http.get(uri.to_s, headers)
109
109
 
110
110
  if file_name
111
- File.open(file_name, 'wb') { |file| file.write(resp.body) }
111
+ ::File.open(file_name, 'wb') { |file| file.write(resp.body) }
112
112
  else
113
113
  resp.body
114
114
  end
@@ -0,0 +1,108 @@
1
+ module Nexpose
2
+
3
+ # Contains the shared methods for the SiteCredential and SharedCredential Objects.
4
+ # See Nexpose::SiteCredential or Nexpose::SharedCredential for additional info.
5
+ class Credential
6
+
7
+ # Mapping of Common Ports.
8
+ DEFAULT_PORTS = { 'cvs' => 2401,
9
+ 'ftp' => 21,
10
+ 'http' => 80,
11
+ 'as400' => 449,
12
+ 'notes' => 1352,
13
+ 'tds' => 1433,
14
+ 'sybase' => 5000,
15
+ 'cifs' => 445,
16
+ 'cifshash' => 445,
17
+ 'oracle' => 1521,
18
+ 'pop' => 110,
19
+ 'postgresql' => 5432,
20
+ 'remote execution' => 512,
21
+ 'snmp' => 161,
22
+ 'snmpv3' => 161,
23
+ 'ssh' => 22,
24
+ 'ssh-key' => 22,
25
+ 'telnet' => 23,
26
+ 'mysql' => 3306,
27
+ 'db2' => 50000 }
28
+
29
+
30
+ # Credential Service/Type Options.
31
+ module Service
32
+ CVS = 'cvs' # Concurrent Versioning System (CVS)
33
+ FTP = 'ftp' # File Transfer Protocol (FTP)
34
+ HTTP = 'http' # Web Site HTTP Authentication
35
+ AS400 = 'as400' # IBM AS/400
36
+ NOTES = 'notes' # Lotus Notes/Domino
37
+ TDS = 'tds' # Microsoft SQL Server
38
+ SYBASE = 'sybase' # Sybase SQL Server
39
+ CIFS = 'cifs' # Microsoft Windows/Samba (SMB/CIFS)
40
+ CIFSHASH = 'cifshash' # Microsoft Windows/Samba LM/NTLM Hash (SMB/CIFS)
41
+ ORACLE = 'oracle' # Oracle
42
+ POP = 'pop' # Post Office Protocol (POP)
43
+ POSTGRESQL = 'postgresql' # PostgreSQL
44
+ REMOTE_EXECUTION = 'remote execution' # Remote Execution
45
+ SNMP = 'snmp' # Simple Network Management Protocol
46
+ SNMPV3 = 'snmpv3' # Simple Network Management Protocol v3
47
+ SSH = 'ssh' # Secure Shell (SSH)
48
+ SSH_KEY = 'ssh-key' # Secure Shell (SSH) Public Key
49
+ TELNET = 'telnet' # TELNET
50
+ MYSQL = 'mysql' # MySQL Server
51
+ DB2 = 'db2' # DB2
52
+ end
53
+
54
+
55
+ # Permission Elevation / Privilege Escalation Types.
56
+ module ElevationType
57
+ NONE = 'NONE'
58
+ SUDO = 'SUDO'
59
+ SUDOSU = 'SUDOSU'
60
+ SU = 'SU'
61
+ PBRUN = 'PBRUN'
62
+ end
63
+
64
+
65
+ # Test this credential against a target where the credentials should apply.
66
+ # Only works for a newly created credential. Loading an existing credential
67
+ # will likely fail.
68
+ #
69
+ # @param [Connection] nsc An active connection to the security console.
70
+ # @param [String] target Target host to check credentials against.
71
+ # @param [Fixnum] engine_id ID of the engine to use for testing credentials.
72
+ # Will default to the local engine if none is provided.
73
+ #
74
+ def test(nsc, target, engine_id = nil, siteid = -1)
75
+ unless engine_id
76
+ engine_id = nsc.engines.find { |e| e.name == 'Local scan engine' }.id
77
+ end
78
+ @port = Credential::DEFAULT_PORTS[@service] if @port.nil?
79
+ parameters = _to_param(target, engine_id, @port, siteid)
80
+ xml = AJAX.form_post(nsc, '/ajax/test_admin_credentials.txml', parameters)
81
+ result = REXML::XPath.first(REXML::Document.new(xml), 'TestAdminCredentialsResult')
82
+ result.attributes['success'].to_i == 1
83
+ end
84
+
85
+
86
+ def _to_param(target, engine_id, port, siteid)
87
+ { engineid: engine_id,
88
+ sc_creds_dev: target,
89
+ sc_creds_svc: @service,
90
+ sc_creds_database: @database,
91
+ sc_creds_domain: @domain,
92
+ sc_creds_uname: @username,
93
+ sc_creds_password: @password,
94
+ sc_creds_pemkey: @pem_key,
95
+ sc_creds_port: port,
96
+ sc_creds_privilegeelevationusername: @privilege_username,
97
+ sc_creds_privilegeelevationpassword: @privilege_password,
98
+ sc_creds_privilegeelevationtype: @privilege_type,
99
+ sc_creds_snmpv3authtype: @auth_type,
100
+ sc_creds_snmpv3privtype: @privacy_type,
101
+ sc_creds_snmpv3privpassword: @privacy_password,
102
+ siteid: siteid }
103
+ end
104
+
105
+ end
106
+
107
+
108
+ end
@@ -54,7 +54,7 @@ module Nexpose
54
54
  end
55
55
 
56
56
  def _to_entity_details
57
- obj = { 'searchCriteria' => @criteria.to_map,
57
+ obj = { 'searchCriteria' => @criteria.to_hash,
58
58
  'name' => @name,
59
59
  'tag' => @description.nil? ? '' : @description,
60
60
  'dynamic' => true,
@@ -283,11 +283,12 @@ module Nexpose
283
283
 
284
284
  # Convert this object into the map format expected by Nexpose.
285
285
  #
286
- def to_map
286
+ def to_hash
287
287
  { 'metadata' => { 'fieldName' => field },
288
288
  'operator' => operator,
289
289
  'values' => Array(value) }
290
290
  end
291
+ alias_method :to_map, :to_hash
291
292
 
292
293
  def self.parse(json)
293
294
  Criterion.new(json['metadata']['fieldName'],
@@ -310,15 +311,16 @@ module Nexpose
310
311
  @match = match.upcase
311
312
  end
312
313
 
313
- def to_map
314
+ def to_hash
314
315
  { 'operator' => @match,
315
- 'criteria' => @criteria.map { |c| c.to_map } }
316
+ 'criteria' => @criteria.map { |c| c.to_hash } }
316
317
  end
318
+ alias_method :to_map, :to_hash
317
319
 
318
320
  # Convert this object into the format expected by Nexpose.
319
321
  #
320
322
  def to_json
321
- JSON.generate(to_map)
323
+ JSON.generate(to_hash)
322
324
  end
323
325
 
324
326
  # Generate the payload needed for a POST request for Asset Filter.
@@ -222,23 +222,23 @@ module Nexpose
222
222
  xml << '</AdhocReportConfig>'
223
223
  end
224
224
 
225
- include XMLUtils
226
- include HTMLUtils
227
-
228
225
  # Generate a report once using a simple configuration.
229
226
  #
230
- # For XML-based reports, only the raw report is returned and not any images.
227
+ # For XML-based reports, only the textual report is returned and not any images.
231
228
  #
232
229
  # @param [Connection] connection Nexpose connection.
233
230
  # @param [Fixnum] timeout How long, in seconds, to wait for the report to
234
231
  # generate. Larger reports can take a significant amount of time.
232
+ # @param [Boolean] raw Whether to bypass response parsing an use the raw
233
+ # response. If this option is used, error will only be exposed by
234
+ # examining Connection#response_xml.
235
235
  # @return Report in text format except for PDF, which returns binary data.
236
236
  #
237
- def generate(connection, timeout = 300)
237
+ def generate(connection, timeout = 300, raw = false)
238
238
  xml = %(<ReportAdhocGenerateRequest session-id="#{connection.session_id}">)
239
239
  xml << to_xml
240
240
  xml << '</ReportAdhocGenerateRequest>'
241
- response = connection.execute(xml, '1.1', timeout: timeout)
241
+ response = connection.execute(xml, '1.1', timeout: timeout, raw: raw)
242
242
  if response.success
243
243
  content_type_response = response.raw_response.header['Content-Type']
244
244
  if content_type_response =~ /multipart\/mixed;\s*boundary=([^\s]+)/
@@ -254,9 +254,9 @@ module Nexpose
254
254
  if /.*base64.*/ =~ part.header.to_s
255
255
  if @format =~ /(?:ht|x)ml/
256
256
  if part.header.to_s =~ %r(text/xml)
257
- return parse_xml(part.content.unpack('m*')[0]).to_s
257
+ return part.content.unpack('m*')[0].to_s
258
258
  elsif part.header.to_s =~ %r(text/html)
259
- return parse_html(part.content.unpack('m*')[0]).to_s
259
+ return part.content.unpack('m*')[0].to_s
260
260
  end
261
261
  else # text|pdf|csv|rtf
262
262
  return part.content.unpack('m*')[0]
@@ -263,7 +263,7 @@ module Nexpose
263
263
  case resp
264
264
  when Net::HTTPSuccess
265
265
  if zip_file
266
- File.open(zip_file, 'wb') { |file| file.write(resp.body) }
266
+ ::File.open(zip_file, 'wb') { |file| file.write(resp.body) }
267
267
  else
268
268
  resp.body
269
269
  end
@@ -296,7 +296,7 @@ module Nexpose
296
296
  data = Rex::MIME::Message.new
297
297
  data.add_part(site_id.to_s, nil, nil, 'form-data; name="siteid"')
298
298
  data.add_part(session_id, nil, nil, 'form-data; name="nexposeCCSessionID"')
299
- scan = File.new(zip_file, 'rb')
299
+ scan = ::File.new(zip_file, 'rb')
300
300
  data.add_part(scan.read, 'application/zip', 'binary',
301
301
  "form-data; name=\"scan\"; filename=\"#{zip_file}\"")
302
302
 
@@ -21,14 +21,16 @@ module Nexpose
21
21
  alias_method :delete_shared_cred, :delete_shared_credential
22
22
  end
23
23
 
24
- class SharedCredentialSummary
24
+ class SharedCredentialSummary < Credential
25
25
 
26
26
  # Unique ID assigned to this credential by Nexpose.
27
27
  attr_accessor :id
28
28
  # Name to identify this credential.
29
29
  attr_accessor :name
30
- # The credential type. See Nexpose::Credential::Type.
31
- attr_accessor :type
30
+ # The credential service/type. See Nexpose::Credential::Service.
31
+ attr_accessor :service
32
+ alias :type :service
33
+ alias :type= :service=
32
34
  # Domain or realm.
33
35
  attr_accessor :domain
34
36
  # User name.
@@ -168,49 +170,6 @@ module Nexpose
168
170
  as_xml.to_s
169
171
  end
170
172
 
171
- # Test this credential against a target where the credentials should apply.
172
- # Only works for a newly created credential. Loading an existing credential
173
- # will likely fail.
174
- #
175
- # @param [Connection] nsc An active connection to the security console.
176
- # @param [String] target Target host to check credentials against.
177
- # @param [Fixnum] engine_id ID of the engine to use for testing credentials.
178
- # Will default to the local engine if none is provided.
179
- #
180
- def test(nsc, target, engine_id = nil)
181
- unless engine_id
182
- local_engine = nsc.engines.find { |e| e.name == 'Local scan engine' }
183
- engine_id = local_engine.id
184
- end
185
-
186
- parameters = _to_param(target, engine_id)
187
- xml = AJAX.form_post(nsc, '/ajax/test_admin_credentials.txml', parameters)
188
- result = REXML::XPath.first(REXML::Document.new(xml), 'TestAdminCredentialsResult')
189
- result.attributes['success'].to_i == 1
190
- end
191
-
192
- def _to_param(target, engine_id)
193
- port = @port
194
- port = Credential::DEFAULT_PORTS[@type] if port.nil?
195
-
196
- { engineid: engine_id,
197
- sc_creds_dev: target,
198
- sc_creds_svc: @type,
199
- sc_creds_database: @database,
200
- sc_creds_domain: @domain,
201
- sc_creds_uname: @username,
202
- sc_creds_password: @password,
203
- sc_creds_pemkey: @pem_key,
204
- sc_creds_port: port,
205
- sc_creds_privilegeelevationusername: @privilege_username,
206
- sc_creds_privilegeelevationpassword: @privilege_password,
207
- sc_creds_privilegeelevationtype: @privilege_type,
208
- sc_creds_snmpv3authtype: @auth_type,
209
- sc_creds_snmpv3privtype: @privacy_type,
210
- sc_creds_snmpv3privpassword: @privacy_password,
211
- siteid: -1 }
212
- end
213
-
214
173
  def self.parse(xml)
215
174
  rexml = REXML::Document.new(xml)
216
175
  rexml.elements.each('Credential') do |c|
@@ -352,7 +352,7 @@ module Nexpose
352
352
  'tag' => @description.nil? ? '' : @description,
353
353
  'riskFactor' => @risk_factor,
354
354
  # 'vCenter' => @discovery_connection_id,
355
- 'searchCriteria' => @criteria.nil? ? { 'operator' => 'AND' } : @criteria.to_map }
355
+ 'searchCriteria' => @criteria.nil? ? { 'operator' => 'AND' } : @criteria.to_hash }
356
356
  json = JSON.generate(details)
357
357
 
358
358
  response = AJAX.post(nsc, uri, json, AJAX::CONTENT_TYPE::JSON)
@@ -494,7 +494,7 @@ module Nexpose
494
494
  end
495
495
 
496
496
  s.elements.each('Credentials/adminCredentials') do |cred|
497
- site.credentials << Credential.parse(cred)
497
+ site.credentials << SiteCredential.parse(cred)
498
498
  end
499
499
 
500
500
  s.elements.each('ScanConfig') do |scan_config|
@@ -6,29 +6,9 @@ module Nexpose
6
6
  # be passed back as is during a Site Save operation. This object
7
7
  # can only be used to create a new set of credentials.
8
8
  #
9
- class Credential
9
+ class SiteCredential < Credential
10
10
  include XMLUtils
11
11
 
12
- DEFAULT_PORTS = { 'cvs' => 2401,
13
- 'ftp' => 21,
14
- 'http' => 80,
15
- 'as400' => 449,
16
- 'notes' => 1352,
17
- 'tds' => 1433,
18
- 'sybase' => 5000,
19
- 'cifs' => 445,
20
- 'cifshash' => 445,
21
- 'oracle' => 1521,
22
- 'pop' => 110,
23
- 'postgresql' => 5432,
24
- 'remote execution' => 512,
25
- 'snmp' => 161,
26
- 'snmpv3' => 161,
27
- 'ssh' => 22,
28
- 'ssh-key' => 22,
29
- 'telnet' => 23,
30
- 'mysql' => 3306,
31
- 'db2' => 50000 }
32
12
 
33
13
  # Security blob for an existing set of credentials
34
14
  attr_accessor :blob
@@ -38,8 +18,6 @@ module Nexpose
38
18
  attr_accessor :host
39
19
  # The port on which to use these credentials.
40
20
  attr_accessor :port
41
- # The user id or username
42
- attr_accessor :userid
43
21
  # The password
44
22
  attr_accessor :password
45
23
  # The realm for these credentials
@@ -63,10 +41,18 @@ module Nexpose
63
41
  # The privacy/encryption pass phrase to use with SNMP v3 credentials
64
42
  attr_accessor :privacy_password
65
43
 
44
+ # Permission elevation type. See Nexpose::Credential::ElevationType.
45
+ attr_accessor :privilege_type
46
+ # The User ID or Username
47
+ attr_accessor :username
48
+ alias :userid :username
49
+ alias :userid= :username=
50
+
51
+
66
52
  def self.for_service(service, user, password, realm = nil, host = nil, port = nil)
67
53
  cred = new
68
54
  cred.service = service
69
- cred.userid = user
55
+ cred.username = user
70
56
  cred.password = password
71
57
  cred.realm = realm
72
58
  cred.host = host
@@ -80,7 +66,7 @@ module Nexpose
80
66
  @priv_username = username
81
67
  @priv_password = password
82
68
  end
83
-
69
+
84
70
  def add_snmpv3_credentials(auth_type, privacy_type, privacy_password)
85
71
  @auth_type = auth_type
86
72
  @privacy_type = privacy_type
@@ -102,9 +88,8 @@ module Nexpose
102
88
 
103
89
  def as_xml
104
90
  attributes = {}
105
-
106
91
  attributes['service'] = @service
107
- attributes['userid'] = @userid
92
+ attributes['userid'] = @username
108
93
  attributes['password'] = @password
109
94
  attributes['realm'] = @realm
110
95
  attributes['host'] = @host
@@ -113,7 +98,7 @@ module Nexpose
113
98
  attributes['privilegeelevationtype'] = @priv_type if @priv_type
114
99
  attributes['privilegeelevationusername'] = @priv_username if @priv_username
115
100
  attributes['privilegeelevationpassword'] = @priv_password if @priv_password
116
-
101
+
117
102
  attributes['snmpv3authtype'] = @auth_type if @auth_type
118
103
  attributes['snmpv3privtype'] = @privacy_type if @privacy_type
119
104
  attributes['snmpv3privpassword'] = @privacy_password if @privacy_password
@@ -139,61 +124,6 @@ module Nexpose
139
124
  to_xml.hash
140
125
  end
141
126
 
142
- # Credential type options.
143
- #
144
- module Type
145
-
146
- # Concurrent Versioning System (CVS)
147
- CVS = 'cvs'
148
- # File Transfer Protocol (FTP)
149
- FTP = 'ftp'
150
- # Web Site HTTP Authentication
151
- HTTP = 'http'
152
- # IBM AS/400
153
- AS400 = 'as400'
154
- # Lotus Notes/Domino
155
- NOTES = 'notes'
156
- # Microsoft SQL Server
157
- TDS = 'tds'
158
- # Sybase SQL Server
159
- SYBASE = 'sybase'
160
- # Microsoft Windows/Samba (SMB/CIFS)
161
- CIFS = 'cifs'
162
- # Microsoft Windows/Samba LM/NTLM Hash (SMB/CIFS)
163
- CIFSHASH = 'cifshash'
164
- # Oracle
165
- ORACLE = 'oracle'
166
- # Post Office Protocol (POP)
167
- POP = 'pop'
168
- # PostgreSQL
169
- POSTGRESQL = 'postgresql'
170
- # Remote Execution
171
- REMOTE_EXECUTION = 'remote execution'
172
- # Simple Network Management Protocol
173
- SNMP = 'snmp'
174
- # Simple Network Management Protocol v3
175
- SNMPV3 = 'snmpv3'
176
- # Secure Shell (SSH)
177
- SSH = 'ssh'
178
- # Secure Shell (SSH) Public Key
179
- SSH_KEY = 'ssh-key'
180
- # TELNET
181
- TELNET = 'telnet'
182
- # MySQL Server
183
- MYSQL = 'mysql'
184
- # DB2
185
- DB2 = 'db2'
186
- end
187
-
188
- # Permission Elevation Types
189
- #
190
- module ElevationType
191
-
192
- NONE = 'NONE'
193
- SUDO = 'SUDO'
194
- SUDOSU = 'SUDOSU'
195
- SU = 'SU'
196
- end
197
127
  end
198
128
 
199
129
  # Object that represents Header name-value pairs, associated with Web Session Authentication.
@@ -259,7 +259,7 @@ module Nexpose
259
259
  'tag_config' => { 'site_ids' => @site_ids,
260
260
  'tag_associated_asset_ids' => @associated_asset_ids,
261
261
  'asset_group_ids' => @asset_group_ids,
262
- 'search_criteria' => @search_criteria ? @search_criteria.to_map : nil
262
+ 'search_criteria' => @search_criteria ? @search_criteria.to_hash : nil
263
263
  }
264
264
  }
265
265
  if @type == Type::Generic::CUSTOM
@@ -6,12 +6,6 @@ module Nexpose
6
6
  end
7
7
  end
8
8
 
9
- module HTMLUtils
10
- def parse_html(html)
11
- Nokogiri::HTML(html, nil, 'UTF-8')
12
- end
13
- end
14
-
15
9
  module XMLUtils
16
10
 
17
11
  def parse_xml(xml)
@@ -116,4 +110,22 @@ module Nexpose
116
110
  time.to_time.utc.strftime('%Y%m%dT%H%M%S.%LZ')
117
111
  end
118
112
  end
113
+
114
+ # Functions for handling attributes as understood by the API.
115
+ # In particular, the API expects a JSON object with the hash defined as:
116
+ # { "key": "key-string",
117
+ # "value": "value-string" }
118
+ #
119
+ module Attributes
120
+ module_function
121
+
122
+ # Convert an array of attributes into a hash consumable by the API.
123
+ #
124
+ # @param [Array[Hash]] arr Array of attributes to convert.
125
+ # @return [Array[Hash]] Array formatted as expected by the API.
126
+ #
127
+ def to_hash(arr)
128
+ arr.map(&:flatten).map { |p| { 'key' => p.first.to_s, 'value' => p.last.to_s } }
129
+ end
130
+ end
119
131
  end
@@ -1,4 +1,4 @@
1
1
  module Nexpose
2
2
  # The latest version of the Nexpose gem
3
- VERSION = '0.8.18'
3
+ VERSION = '0.9.0'
4
4
  end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'nexpose/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'nexpose'
8
+ s.version = Nexpose::VERSION
9
+ s.homepage = 'https://github.com/rapid7/nexpose-client'
10
+ s.summary = 'Ruby API for Rapid7 Nexpose'
11
+ s.description = 'This gem provides a Ruby API to the Nexpose vulnerability management product by Rapid7.'
12
+ s.license = 'BSD'
13
+ s.authors = ['HD Moore', 'Chris Lee', 'Michael Daines', 'Brandon Turner']
14
+ s.email = ['hd_moore@rapid7.com', 'christopher_lee@rapid7.com', 'michael_daines@rapid7.com', 'brandon_turner@rapid7.com' ]
15
+ s.files = Dir['[A-Z]*'] + Dir['lib/**/*']
16
+ s.require_paths = ['lib']
17
+ s.extra_rdoc_files = ['README.markdown']
18
+ s.required_ruby_version = '>= 1.9'
19
+ s.platform = 'ruby'
20
+
21
+ s.add_runtime_dependency('rex', '~> 2.0.5', '>= 2.0.5')
22
+
23
+ s.add_development_dependency('bundler', '~> 1.3')
24
+ 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.18
4
+ version: 0.9.0
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-12-15 00:00:00.000000000 Z
14
+ date: 2014-12-31 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rex
@@ -19,40 +19,20 @@ dependencies:
19
19
  requirements:
20
20
  - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: 2.0.4
22
+ version: 2.0.5
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 2.0.4
25
+ version: 2.0.5
26
26
  type: :runtime
27
27
  prerelease: false
28
28
  version_requirements: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 2.0.4
32
+ version: 2.0.5
33
33
  - - ">="
34
34
  - !ruby/object:Gem::Version
35
- version: 2.0.4
36
- - !ruby/object:Gem::Dependency
37
- name: nokogiri
38
- requirement: !ruby/object:Gem::Requirement
39
- requirements:
40
- - - "~>"
41
- - !ruby/object:Gem::Version
42
- version: '1.6'
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- version: 1.6.2
46
- type: :runtime
47
- prerelease: false
48
- version_requirements: !ruby/object:Gem::Requirement
49
- requirements:
50
- - - "~>"
51
- - !ruby/object:Gem::Version
52
- version: '1.6'
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: 1.6.2
35
+ version: 2.0.5
56
36
  - !ruby/object:Gem::Dependency
57
37
  name: bundler
58
38
  requirement: !ruby/object:Gem::Requirement
@@ -92,7 +72,7 @@ files:
92
72
  - lib/nexpose/common.rb
93
73
  - lib/nexpose/connection.rb
94
74
  - lib/nexpose/console.rb
95
- - lib/nexpose/creds.rb
75
+ - lib/nexpose/credential.rb
96
76
  - lib/nexpose/dag.rb
97
77
  - lib/nexpose/data_table.rb
98
78
  - lib/nexpose/device.rb
@@ -112,10 +92,11 @@ files:
112
92
  - lib/nexpose/role.rb
113
93
  - lib/nexpose/scan.rb
114
94
  - lib/nexpose/scan_template.rb
115
- - lib/nexpose/shared_cred.rb
95
+ - lib/nexpose/shared_credential.rb
116
96
  - lib/nexpose/silo.rb
117
97
  - lib/nexpose/silo_profile.rb
118
98
  - lib/nexpose/site.rb
99
+ - lib/nexpose/site_credential.rb
119
100
  - lib/nexpose/tag.rb
120
101
  - lib/nexpose/tag/criteria.rb
121
102
  - lib/nexpose/ticket.rb
@@ -124,6 +105,7 @@ files:
124
105
  - lib/nexpose/version.rb
125
106
  - lib/nexpose/vuln.rb
126
107
  - lib/nexpose/vuln_exception.rb
108
+ - nexpose.gemspec
127
109
  homepage: https://github.com/rapid7/nexpose-client
128
110
  licenses:
129
111
  - BSD
@@ -144,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
126
  version: '0'
145
127
  requirements: []
146
128
  rubyforge_project:
147
- rubygems_version: 2.4.3
129
+ rubygems_version: 2.4.5
148
130
  signing_key:
149
131
  specification_version: 4
150
132
  summary: Ruby API for Rapid7 Nexpose