nexpose 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/nexpose/connection.rb +0 -2
- data/lib/nexpose/filter.rb +33 -23
- data/lib/nexpose/site.rb +1 -1
- data/lib/nexpose/tag.rb +23 -25
- data/lib/nexpose/tag/criteria.rb +22 -30
- data/lib/nexpose/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c31ee4438b71d0e7787d9cfad2720d477e7988a
|
4
|
+
data.tar.gz: d33c662be936d2ffd49987a3cf12d4f49899f733
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52e8d242d94b4965f27c314b285d6a1937ba9647e646a148557961071e64271fefd6fd926ebd483126cbc5ee8fafb0828aa30cae7871d4253146d238d025c486
|
7
|
+
data.tar.gz: fc5065fe8f438171d8e2942d5e624a6e2ea22c39d851fe099adaf8f485ef8c4e04e241bbb0cc7ca282c2ec61cd61100960e329f3001c42698982433ece4f0b59
|
data/lib/nexpose/connection.rb
CHANGED
data/lib/nexpose/filter.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
module Nexpose
|
2
|
-
|
2
|
+
# Object that represents a connection to a Nexpose Security Console.
|
3
3
|
class Connection
|
4
|
-
|
5
4
|
# Perform an asset filter search that will locate assets matching the
|
6
5
|
# provided conditions.
|
7
6
|
#
|
@@ -53,9 +52,9 @@ module Nexpose
|
|
53
52
|
# Only these values are accepted for a field value.
|
54
53
|
#
|
55
54
|
module Field
|
56
|
-
|
57
55
|
# Search for an Asset by name.
|
58
|
-
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, CONTAINS,
|
56
|
+
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, CONTAINS,
|
57
|
+
# NOT_CONTAINS
|
59
58
|
ASSET = 'ASSET'
|
60
59
|
|
61
60
|
# Search for an Asset by CVE ID
|
@@ -91,7 +90,8 @@ module Nexpose
|
|
91
90
|
CVSS_SCORE = 'CVSS_SCORE'
|
92
91
|
|
93
92
|
# Valid Operators: IN, NOT_IN
|
94
|
-
# Valid Values (See Value::HostType): UNKNOWN, VIRTUAL, HYPERVISOR,
|
93
|
+
# Valid Values (See Value::HostType): UNKNOWN, VIRTUAL, HYPERVISOR,
|
94
|
+
# BARE_METAL
|
95
95
|
HOST_TYPE = 'HOST_TYPE'
|
96
96
|
|
97
97
|
# Valid Operators: IN, NOT_IN
|
@@ -138,17 +138,21 @@ module Nexpose
|
|
138
138
|
# Valid Operators: CONTAINS, NOT_CONTAINS
|
139
139
|
SOFTWARE = 'SOFTWARE'
|
140
140
|
|
141
|
-
# Valid Operators: IS, IS_NOT, GREATER_THAN, LESS_THAN, IS_APPLIED,
|
141
|
+
# Valid Operators: IS, IS_NOT, GREATER_THAN, LESS_THAN, IS_APPLIED,
|
142
|
+
# IS_NOT_APPLIED
|
142
143
|
# Valid Values: VERY_HIGH, HIGH, NORMAL, LOW, VERY_LOW
|
143
144
|
USER_ADDED_CRITICALITY_LEVEL = 'TAG_CRITICALITY'
|
144
145
|
|
145
|
-
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED,
|
146
|
+
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED,
|
147
|
+
# IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
|
146
148
|
USER_ADDED_CUSTOM_TAG = 'TAG'
|
147
149
|
|
148
|
-
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED,
|
150
|
+
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED,
|
151
|
+
# IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
|
149
152
|
USER_ADDED_TAG_LOCATION = 'TAG_LOCATION'
|
150
153
|
|
151
|
-
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED,
|
154
|
+
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED,
|
155
|
+
# IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
|
152
156
|
USER_ADDED_TAG_OWNER = 'TAG_OWNER'
|
153
157
|
|
154
158
|
# Valid Operators: ARE
|
@@ -160,11 +164,13 @@ module Nexpose
|
|
160
164
|
VULNERABILITY = 'VULNERABILITY'
|
161
165
|
|
162
166
|
# Valid Operators: INCLUDE, DO_NOT_INCLUDE
|
163
|
-
# Valid Values (See Value::VulnerabilityExposure): MALWARE, METASPLOIT,
|
167
|
+
# Valid Values (See Value::VulnerabilityExposure): MALWARE, METASPLOIT,
|
168
|
+
# DATABASE
|
164
169
|
VULNERABILITY_EXPOSURES = 'VULNERABILITY_EXPOSURES'
|
165
170
|
|
166
171
|
# Search by VULNERABILITY CATEGORY
|
167
|
-
# Valid Operators: IS, IS_NOT, CONTAINS, NOT_CONTAINS, STARTS_WITH,
|
172
|
+
# Valid Operators: IS, IS_NOT, CONTAINS, NOT_CONTAINS, STARTS_WITH,
|
173
|
+
# ENDS_WITH
|
168
174
|
VULN_CATEGORY = 'VULN_CATEGORY'
|
169
175
|
end
|
170
176
|
|
@@ -199,31 +205,35 @@ module Nexpose
|
|
199
205
|
# Specialized values used by certain search fields
|
200
206
|
#
|
201
207
|
module Value
|
202
|
-
|
208
|
+
# Constants for filtering on access complexity.
|
203
209
|
module AccessComplexity
|
204
210
|
LOW = 'L'
|
205
211
|
MEDIUM = 'M'
|
206
212
|
HIGH = 'H'
|
207
213
|
end
|
208
214
|
|
215
|
+
# Constants for filtering on access vector.
|
209
216
|
module AccessVector
|
210
217
|
LOCAL = 'L'
|
211
218
|
ADJACENT = 'A'
|
212
219
|
NETWORK = 'N'
|
213
220
|
end
|
214
221
|
|
222
|
+
# Constants for filtering on whether authentication is required.
|
215
223
|
module AuthenticationRequired
|
216
224
|
NONE = 'N'
|
217
225
|
SINGLE = 'S'
|
218
226
|
MULTIPLE = 'M'
|
219
227
|
end
|
220
228
|
|
229
|
+
# Constants for filtering on CVSS impact.
|
221
230
|
module CVSSImpact
|
222
231
|
NONE = 'N'
|
223
232
|
PARTIAL = 'P'
|
224
233
|
COMPLETE = 'C'
|
225
234
|
end
|
226
235
|
|
236
|
+
# Constants for filtering on host type.
|
227
237
|
module HostType
|
228
238
|
UNKNOWN = '0'
|
229
239
|
VIRTUAL = '1'
|
@@ -231,26 +241,31 @@ module Nexpose
|
|
231
241
|
BARE_METAL = '3'
|
232
242
|
end
|
233
243
|
|
244
|
+
# Constants for filtering on IP type.
|
234
245
|
module IPType
|
235
246
|
IPv4 = '0'
|
236
247
|
IPv6 = '1'
|
237
248
|
end
|
238
249
|
|
250
|
+
# Constants for filtering on PCI compliance.
|
239
251
|
module PCICompliance
|
240
252
|
PASS = '1'
|
241
253
|
FAIL = '0'
|
242
254
|
end
|
243
255
|
|
256
|
+
# Constants for filtering on scan date.
|
244
257
|
module ScanDate
|
245
258
|
# Pass this format to #strftime() to get expected format for requests.
|
246
259
|
FORMAT = '%m/%d/%Y'
|
247
260
|
end
|
248
261
|
|
262
|
+
# Constants for filtering on vulnerability validations.
|
249
263
|
module ValidatedVulnerability
|
250
264
|
NOT_PRESENT = 1
|
251
265
|
PRESENT = 0
|
252
266
|
end
|
253
267
|
|
268
|
+
# Constants for filtering on vulnerability exposure.
|
254
269
|
module VulnerabilityExposure
|
255
270
|
MALWARE = 'type:"malware_type", name:"malwarekit"'
|
256
271
|
# TODO: A problem in Nexpose causes these values to not be constant.
|
@@ -263,7 +278,6 @@ module Nexpose
|
|
263
278
|
# Individual search criterion.
|
264
279
|
#
|
265
280
|
class Criterion
|
266
|
-
|
267
281
|
# Search field. One of Nexpose::Search::Field
|
268
282
|
# @see Nexpose::Search::Field for any restrictions on the other attibutes.
|
269
283
|
attr_accessor :field
|
@@ -274,8 +288,8 @@ module Nexpose
|
|
274
288
|
|
275
289
|
def initialize(field, operator, value = '')
|
276
290
|
@field, @operator = field.upcase, operator.upcase
|
277
|
-
if value.
|
278
|
-
@value = value.map
|
291
|
+
if value.is_a? Array
|
292
|
+
@value = value.map(&:to_s)
|
279
293
|
else
|
280
294
|
@value = value.to_s
|
281
295
|
end
|
@@ -283,12 +297,11 @@ module Nexpose
|
|
283
297
|
|
284
298
|
# Convert this object into the map format expected by Nexpose.
|
285
299
|
#
|
286
|
-
def
|
300
|
+
def to_h
|
287
301
|
{ 'metadata' => { 'fieldName' => field },
|
288
302
|
'operator' => operator,
|
289
303
|
'values' => Array(value) }
|
290
304
|
end
|
291
|
-
alias_method :to_map, :to_hash
|
292
305
|
|
293
306
|
def self.parse(json)
|
294
307
|
Criterion.new(json['metadata']['fieldName'],
|
@@ -300,7 +313,6 @@ module Nexpose
|
|
300
313
|
# Join search criteria for an asset filter search or dynamic asset group.
|
301
314
|
#
|
302
315
|
class Criteria
|
303
|
-
|
304
316
|
# Whether to match any or all filters. One of 'OR' or 'AND'.
|
305
317
|
attr_accessor :match
|
306
318
|
# Array of criteria to match against.
|
@@ -311,16 +323,15 @@ module Nexpose
|
|
311
323
|
@match = match.upcase
|
312
324
|
end
|
313
325
|
|
314
|
-
def
|
326
|
+
def to_h
|
315
327
|
{ 'operator' => @match,
|
316
|
-
'criteria' => @criteria.map
|
328
|
+
'criteria' => @criteria.map(&:to_h) }
|
317
329
|
end
|
318
|
-
alias_method :to_map, :to_hash
|
319
330
|
|
320
331
|
# Convert this object into the format expected by Nexpose.
|
321
332
|
#
|
322
333
|
def to_json
|
323
|
-
JSON.generate(
|
334
|
+
JSON.generate(to_h)
|
324
335
|
end
|
325
336
|
|
326
337
|
# Generate the payload needed for a POST request for Asset Filter.
|
@@ -352,7 +363,6 @@ module Nexpose
|
|
352
363
|
# Asset data as returned by an Asset Filter search.
|
353
364
|
#
|
354
365
|
class FilteredAsset
|
355
|
-
|
356
366
|
# Unique identifier of this asset. Also known as device ID.
|
357
367
|
attr_reader :id
|
358
368
|
|
data/lib/nexpose/site.rb
CHANGED
@@ -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.
|
355
|
+
'searchCriteria' => @criteria.nil? ? { 'operator' => 'AND' } : @criteria.to_h }
|
356
356
|
json = JSON.generate(details)
|
357
357
|
|
358
358
|
response = AJAX.post(nsc, uri, json, AJAX::CONTENT_TYPE::JSON)
|
data/lib/nexpose/tag.rb
CHANGED
@@ -8,7 +8,7 @@ module Nexpose
|
|
8
8
|
#
|
9
9
|
def tags
|
10
10
|
tag_summary = []
|
11
|
-
tags = JSON.parse(AJAX.get(self, '/api/2.0/tags', AJAX::CONTENT_TYPE::JSON, { per_page:
|
11
|
+
tags = JSON.parse(AJAX.get(self, '/api/2.0/tags', AJAX::CONTENT_TYPE::JSON, { per_page: 2_147_483_647 }))
|
12
12
|
tags['resources'].each do |json|
|
13
13
|
tag_summary << TagSummary.parse(json)
|
14
14
|
end
|
@@ -31,7 +31,7 @@ module Nexpose
|
|
31
31
|
#
|
32
32
|
def asset_tags(asset_id)
|
33
33
|
tag_summary = []
|
34
|
-
asset_tag = JSON.parse(AJAX.get(self, "/api/2.0/assets/#{asset_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page:
|
34
|
+
asset_tag = JSON.parse(AJAX.get(self, "/api/2.0/assets/#{asset_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page: 2_147_483_647 }))
|
35
35
|
asset_tag['resources'].select { |r| r['asset_ids'].find { |i| i == asset_id } }.each do |json|
|
36
36
|
tag_summary << TagSummary.parse(json)
|
37
37
|
end
|
@@ -55,7 +55,7 @@ module Nexpose
|
|
55
55
|
#
|
56
56
|
def site_tags(site_id)
|
57
57
|
tag_summary = []
|
58
|
-
site_tag = JSON.parse(AJAX.get(self, "/api/2.0/sites/#{site_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page:
|
58
|
+
site_tag = JSON.parse(AJAX.get(self, "/api/2.0/sites/#{site_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page: 2_147_483_647 }))
|
59
59
|
site_tag['resources'].each do |json|
|
60
60
|
tag_summary << TagSummary.parse(json)
|
61
61
|
end
|
@@ -79,7 +79,7 @@ module Nexpose
|
|
79
79
|
#
|
80
80
|
def asset_group_tags(asset_group_id)
|
81
81
|
tag_summary = []
|
82
|
-
asset_group_tag = JSON.parse(AJAX.get(self, "/api/2.0/asset_groups/#{asset_group_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page:
|
82
|
+
asset_group_tag = JSON.parse(AJAX.get(self, "/api/2.0/asset_groups/#{asset_group_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page: 2_147_483_647 }))
|
83
83
|
asset_group_tag['resources'].each do |json|
|
84
84
|
tag_summary << TagSummary.parse(json)
|
85
85
|
end
|
@@ -252,14 +252,12 @@ module Nexpose
|
|
252
252
|
'tag_name' => @name,
|
253
253
|
'tag_type' => @type,
|
254
254
|
'tag_id' => @id,
|
255
|
-
'attributes' => [
|
256
|
-
|
257
|
-
'tag_attribute_value' => @source }
|
258
|
-
],
|
255
|
+
'attributes' => [{ 'tag_attribute_name' => 'SOURCE',
|
256
|
+
'tag_attribute_value' => @source }],
|
259
257
|
'tag_config' => { 'site_ids' => @site_ids,
|
260
258
|
'tag_associated_asset_ids' => @associated_asset_ids,
|
261
259
|
'asset_group_ids' => @asset_group_ids,
|
262
|
-
'search_criteria' => @search_criteria ? @search_criteria.
|
260
|
+
'search_criteria' => @search_criteria ? @search_criteria.to_h : nil
|
263
261
|
}
|
264
262
|
}
|
265
263
|
if @type == Type::Generic::CUSTOM
|
@@ -306,8 +304,9 @@ module Nexpose
|
|
306
304
|
# @return [Fixnum] ID of applied tag
|
307
305
|
#
|
308
306
|
def add_to_asset(connection, asset_id)
|
309
|
-
params =
|
310
|
-
|
307
|
+
params = to_json_for_add
|
308
|
+
url = "/api/2.0/assets/#{asset_id}/tags"
|
309
|
+
uri = AJAX.post(connection, url, params, AJAX::CONTENT_TYPE::JSON)
|
311
310
|
@id = uri.split('/').last.to_i
|
312
311
|
end
|
313
312
|
|
@@ -318,8 +317,9 @@ module Nexpose
|
|
318
317
|
# @return [Fixnum] ID of applied tag
|
319
318
|
#
|
320
319
|
def add_to_site(connection, site_id)
|
321
|
-
params =
|
322
|
-
|
320
|
+
params = to_json_for_add
|
321
|
+
url = "/api/2.0/sites/#{site_id}/tags"
|
322
|
+
uri = AJAX.post(connection, url, params, AJAX::CONTENT_TYPE::JSON)
|
323
323
|
@id = uri.split('/').last.to_i
|
324
324
|
end
|
325
325
|
|
@@ -330,26 +330,24 @@ module Nexpose
|
|
330
330
|
# @return [Fixnum] ID of applied tag
|
331
331
|
#
|
332
332
|
def add_to_group(connection, group_id)
|
333
|
-
params =
|
334
|
-
|
333
|
+
params = to_json_for_add
|
334
|
+
url = "/api/2.0/asset_groups/#{group_id}/tags"
|
335
|
+
uri = AJAX.post(connection, url, params, AJAX::CONTENT_TYPE::JSON)
|
335
336
|
@id = uri.split('/').last.to_i
|
336
337
|
end
|
337
338
|
alias_method :add_to_asset_group, :add_to_group
|
338
339
|
|
339
340
|
private
|
340
341
|
|
341
|
-
def
|
342
|
+
def to_json_for_add
|
342
343
|
if @id == -1
|
343
|
-
json = {
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
{ 'tag_attribute_name' => 'SOURCE',
|
348
|
-
'tag_attribute_value' => @source }
|
349
|
-
],
|
350
|
-
}
|
344
|
+
json = { 'tag_name' => @name,
|
345
|
+
'tag_type' => @type,
|
346
|
+
'attributes' => [{ 'tag_attribute_name' => 'SOURCE',
|
347
|
+
'tag_attribute_value' => @source }] }
|
351
348
|
if @type == Tag::Type::Generic::CUSTOM
|
352
|
-
json['attributes'] << { 'tag_attribute_name' => 'COLOR',
|
349
|
+
json['attributes'] << { 'tag_attribute_name' => 'COLOR',
|
350
|
+
'tag_attribute_value' => @color }
|
353
351
|
end
|
354
352
|
params = JSON.generate(json)
|
355
353
|
else
|
data/lib/nexpose/tag/criteria.rb
CHANGED
@@ -1,45 +1,37 @@
|
|
1
1
|
module Nexpose
|
2
2
|
class Tag
|
3
|
-
|
3
|
+
# Override of filter criterion to account for proper JSON naming.
|
4
|
+
#
|
4
5
|
class Criterion < Nexpose::Criterion
|
5
|
-
|
6
|
-
def
|
7
|
-
{
|
8
|
-
|
9
|
-
|
10
|
-
}
|
6
|
+
# Convert to Hash, which can be converted to JSON for API calls.
|
7
|
+
def to_h
|
8
|
+
{ operator: operator,
|
9
|
+
values: Array(value),
|
10
|
+
field_name: field }
|
11
11
|
end
|
12
12
|
|
13
|
+
# Create a Criterion object from a JSON-derived Hash.
|
14
|
+
#
|
15
|
+
# @param [Hash] json JSON-derived Hash of a Criterion object.
|
16
|
+
# @return [Criterion] Parsed object.
|
17
|
+
#
|
13
18
|
def self.parse(json)
|
14
|
-
|
15
|
-
json['operator'],
|
16
|
-
json['values'])
|
19
|
+
new(json['field_name'], json['operator'], json['values'])
|
17
20
|
end
|
18
|
-
|
19
21
|
end
|
20
22
|
|
23
|
+
# Override of filter criteria to account for different parsing from JSON.
|
24
|
+
#
|
21
25
|
class Criteria < Nexpose::Criteria
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
def to_map
|
28
|
-
{ 'criteria' => @criteria.map { |c| c.to_map },
|
29
|
-
'operator' => @match
|
30
|
-
}
|
31
|
-
end
|
32
|
-
|
26
|
+
# Create a Criteria object from a JSON-derived Hash.
|
27
|
+
#
|
28
|
+
# @param [Hash] json JSON-derived Hash of a Criteria object.
|
29
|
+
# @return [Criteria] Parsed object.
|
30
|
+
#
|
33
31
|
def self.parse(json)
|
34
|
-
|
35
|
-
json['
|
36
|
-
ret.criteria << Criterion.parse(c)
|
37
|
-
end
|
38
|
-
ret
|
32
|
+
criteria = json['criteria'].map { |c| Criterion.parse(c) }
|
33
|
+
new(criteria, json['operator'])
|
39
34
|
end
|
40
|
-
|
41
35
|
end
|
42
36
|
end
|
43
37
|
end
|
44
|
-
|
45
|
-
|
data/lib/nexpose/version.rb
CHANGED
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.9.
|
4
|
+
version: 0.9.1
|
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:
|
14
|
+
date: 2015-01-02 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rex
|