Skip to content

Commit

Permalink
Extend #94 changes to tag criteria.
Browse files Browse the repository at this point in the history
Missed during the refactor to address the to_map method.

Converting to using to_h over to_hash, the logic being that the
method is a pure hash implementation, and not a custom serialization
Hash.

Adds additional method and module documentation that was missing.
  • Loading branch information
mdaines-r7 committed Jan 2, 2015
1 parent dc04d20 commit 942401e
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 81 deletions.
2 changes: 0 additions & 2 deletions lib/nexpose/connection.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
module Nexpose

# === Description
# Object that represents a connection to a Nexpose Security Console.
#
# === Examples
Expand Down
56 changes: 33 additions & 23 deletions lib/nexpose/filter.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module Nexpose

# Object that represents a connection to a Nexpose Security Console.
class Connection

# Perform an asset filter search that will locate assets matching the
# provided conditions.
#
Expand Down Expand Up @@ -53,9 +52,9 @@ module Search
# Only these values are accepted for a field value.
#
module Field

# Search for an Asset by name.
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, CONTAINS, NOT_CONTAINS
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, CONTAINS,
# NOT_CONTAINS
ASSET = 'ASSET'

# Search for an Asset by CVE ID
Expand Down Expand Up @@ -91,7 +90,8 @@ module Field
CVSS_SCORE = 'CVSS_SCORE'

# Valid Operators: IN, NOT_IN
# Valid Values (See Value::HostType): UNKNOWN, VIRTUAL, HYPERVISOR, BARE_METAL
# Valid Values (See Value::HostType): UNKNOWN, VIRTUAL, HYPERVISOR,
# BARE_METAL
HOST_TYPE = 'HOST_TYPE'

# Valid Operators: IN, NOT_IN
Expand Down Expand Up @@ -138,17 +138,21 @@ module Field
# Valid Operators: CONTAINS, NOT_CONTAINS
SOFTWARE = 'SOFTWARE'

# Valid Operators: IS, IS_NOT, GREATER_THAN, LESS_THAN, IS_APPLIED, IS_NOT_APPLIED
# Valid Operators: IS, IS_NOT, GREATER_THAN, LESS_THAN, IS_APPLIED,
# IS_NOT_APPLIED
# Valid Values: VERY_HIGH, HIGH, NORMAL, LOW, VERY_LOW
USER_ADDED_CRITICALITY_LEVEL = 'TAG_CRITICALITY'

# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED, IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED,
# IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
USER_ADDED_CUSTOM_TAG = 'TAG'

# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED, IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED,
# IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
USER_ADDED_TAG_LOCATION = 'TAG_LOCATION'

# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED, IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
# Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED,
# IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
USER_ADDED_TAG_OWNER = 'TAG_OWNER'

# Valid Operators: ARE
Expand All @@ -160,11 +164,13 @@ module Field
VULNERABILITY = 'VULNERABILITY'

# Valid Operators: INCLUDE, DO_NOT_INCLUDE
# Valid Values (See Value::VulnerabilityExposure): MALWARE, METASPLOIT, DATABASE
# Valid Values (See Value::VulnerabilityExposure): MALWARE, METASPLOIT,
# DATABASE
VULNERABILITY_EXPOSURES = 'VULNERABILITY_EXPOSURES'

# Search by VULNERABILITY CATEGORY
# Valid Operators: IS, IS_NOT, CONTAINS, NOT_CONTAINS, STARTS_WITH, ENDS_WITH
# Valid Operators: IS, IS_NOT, CONTAINS, NOT_CONTAINS, STARTS_WITH,
# ENDS_WITH
VULN_CATEGORY = 'VULN_CATEGORY'
end

Expand Down Expand Up @@ -199,58 +205,67 @@ module Operator
# Specialized values used by certain search fields
#
module Value

# Constants for filtering on access complexity.
module AccessComplexity
LOW = 'L'
MEDIUM = 'M'
HIGH = 'H'
end

# Constants for filtering on access vector.
module AccessVector
LOCAL = 'L'
ADJACENT = 'A'
NETWORK = 'N'
end

# Constants for filtering on whether authentication is required.
module AuthenticationRequired
NONE = 'N'
SINGLE = 'S'
MULTIPLE = 'M'
end

# Constants for filtering on CVSS impact.
module CVSSImpact
NONE = 'N'
PARTIAL = 'P'
COMPLETE = 'C'
end

# Constants for filtering on host type.
module HostType
UNKNOWN = '0'
VIRTUAL = '1'
HYPERVISOR = '2'
BARE_METAL = '3'
end

# Constants for filtering on IP type.
module IPType
IPv4 = '0'
IPv6 = '1'
end

# Constants for filtering on PCI compliance.
module PCICompliance
PASS = '1'
FAIL = '0'
end

# Constants for filtering on scan date.
module ScanDate
# Pass this format to #strftime() to get expected format for requests.
FORMAT = '%m/%d/%Y'
end

# Constants for filtering on vulnerability validations.
module ValidatedVulnerability
NOT_PRESENT = 1
PRESENT = 0
end

# Constants for filtering on vulnerability exposure.
module VulnerabilityExposure
MALWARE = 'type:"malware_type", name:"malwarekit"'
# TODO: A problem in Nexpose causes these values to not be constant.
Expand All @@ -263,7 +278,6 @@ module VulnerabilityExposure
# Individual search criterion.
#
class Criterion

# Search field. One of Nexpose::Search::Field
# @see Nexpose::Search::Field for any restrictions on the other attibutes.
attr_accessor :field
Expand All @@ -274,21 +288,20 @@ class Criterion

def initialize(field, operator, value = '')
@field, @operator = field.upcase, operator.upcase
if value.kind_of? Array
@value = value.map { |v| v.to_s }
if value.is_a? Array
@value = value.map(&:to_s)
else
@value = value.to_s
end
end

# Convert this object into the map format expected by Nexpose.
#
def to_hash
def to_h
{ 'metadata' => { 'fieldName' => field },
'operator' => operator,
'values' => Array(value) }
end
alias_method :to_map, :to_hash

def self.parse(json)
Criterion.new(json['metadata']['fieldName'],
Expand All @@ -300,7 +313,6 @@ def self.parse(json)
# Join search criteria for an asset filter search or dynamic asset group.
#
class Criteria

# Whether to match any or all filters. One of 'OR' or 'AND'.
attr_accessor :match
# Array of criteria to match against.
Expand All @@ -311,16 +323,15 @@ def initialize(criteria = [], match = 'AND')
@match = match.upcase
end

def to_hash
def to_h
{ 'operator' => @match,
'criteria' => @criteria.map { |c| c.to_hash } }
'criteria' => @criteria.map(&:to_h) }
end
alias_method :to_map, :to_hash

# Convert this object into the format expected by Nexpose.
#
def to_json
JSON.generate(to_hash)
JSON.generate(to_h)
end

# Generate the payload needed for a POST request for Asset Filter.
Expand Down Expand Up @@ -352,7 +363,6 @@ def self.parse(json)
# Asset data as returned by an Asset Filter search.
#
class FilteredAsset

# Unique identifier of this asset. Also known as device ID.
attr_reader :id

Expand Down
2 changes: 1 addition & 1 deletion lib/nexpose/site.rb
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ def save_dynamic_criteria(nsc)
'tag' => @description.nil? ? '' : @description,
'riskFactor' => @risk_factor,
# 'vCenter' => @discovery_connection_id,
'searchCriteria' => @criteria.nil? ? { 'operator' => 'AND' } : @criteria.to_hash }
'searchCriteria' => @criteria.nil? ? { 'operator' => 'AND' } : @criteria.to_h }
json = JSON.generate(details)

response = AJAX.post(nsc, uri, json, AJAX::CONTENT_TYPE::JSON)
Expand Down
48 changes: 23 additions & 25 deletions lib/nexpose/tag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Connection
#
def tags
tag_summary = []
tags = JSON.parse(AJAX.get(self, '/api/2.0/tags', AJAX::CONTENT_TYPE::JSON, { per_page: 2147483647 }))
tags = JSON.parse(AJAX.get(self, '/api/2.0/tags', AJAX::CONTENT_TYPE::JSON, { per_page: 2_147_483_647 }))
tags['resources'].each do |json|
tag_summary << TagSummary.parse(json)
end
Expand All @@ -31,7 +31,7 @@ def delete_tag(tag_id)
#
def asset_tags(asset_id)
tag_summary = []
asset_tag = JSON.parse(AJAX.get(self, "/api/2.0/assets/#{asset_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page: 2147483647 }))
asset_tag = JSON.parse(AJAX.get(self, "/api/2.0/assets/#{asset_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page: 2_147_483_647 }))
asset_tag['resources'].select { |r| r['asset_ids'].find { |i| i == asset_id } }.each do |json|
tag_summary << TagSummary.parse(json)
end
Expand All @@ -55,7 +55,7 @@ def remove_tag_from_asset(asset_id, tag_id)
#
def site_tags(site_id)
tag_summary = []
site_tag = JSON.parse(AJAX.get(self, "/api/2.0/sites/#{site_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page: 2147483647 }))
site_tag = JSON.parse(AJAX.get(self, "/api/2.0/sites/#{site_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page: 2_147_483_647 }))
site_tag['resources'].each do |json|
tag_summary << TagSummary.parse(json)
end
Expand All @@ -79,7 +79,7 @@ def remove_tag_from_site(site_id, tag_id)
#
def asset_group_tags(asset_group_id)
tag_summary = []
asset_group_tag = JSON.parse(AJAX.get(self, "/api/2.0/asset_groups/#{asset_group_id}/tags", AJAX::CONTENT_TYPE::JSON, { per_page: 2147483647 }))
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 }))
asset_group_tag['resources'].each do |json|
tag_summary << TagSummary.parse(json)
end
Expand Down Expand Up @@ -252,14 +252,12 @@ def to_json
'tag_name' => @name,
'tag_type' => @type,
'tag_id' => @id,
'attributes' => [
{ 'tag_attribute_name' => 'SOURCE',
'tag_attribute_value' => @source }
],
'attributes' => [{ 'tag_attribute_name' => 'SOURCE',
'tag_attribute_value' => @source }],
'tag_config' => { 'site_ids' => @site_ids,
'tag_associated_asset_ids' => @associated_asset_ids,
'asset_group_ids' => @asset_group_ids,
'search_criteria' => @search_criteria ? @search_criteria.to_hash : nil
'search_criteria' => @search_criteria ? @search_criteria.to_h : nil
}
}
if @type == Type::Generic::CUSTOM
Expand Down Expand Up @@ -306,8 +304,9 @@ def self.parse(json)
# @return [Fixnum] ID of applied tag
#
def add_to_asset(connection, asset_id)
params = _to_json_for_add
uri = AJAX.post(connection, "/api/2.0/assets/#{asset_id}/tags", params, AJAX::CONTENT_TYPE::JSON)
params = to_json_for_add
url = "/api/2.0/assets/#{asset_id}/tags"
uri = AJAX.post(connection, url, params, AJAX::CONTENT_TYPE::JSON)
@id = uri.split('/').last.to_i
end

Expand All @@ -318,8 +317,9 @@ def add_to_asset(connection, asset_id)
# @return [Fixnum] ID of applied tag
#
def add_to_site(connection, site_id)
params = _to_json_for_add
uri = AJAX.post(connection, "/api/2.0/sites/#{site_id}/tags", params, AJAX::CONTENT_TYPE::JSON)
params = to_json_for_add
url = "/api/2.0/sites/#{site_id}/tags"
uri = AJAX.post(connection, url, params, AJAX::CONTENT_TYPE::JSON)
@id = uri.split('/').last.to_i
end

Expand All @@ -330,26 +330,24 @@ def add_to_site(connection, site_id)
# @return [Fixnum] ID of applied tag
#
def add_to_group(connection, group_id)
params = _to_json_for_add
uri = AJAX.post(connection, "/api/2.0/asset_groups/#{group_id}/tags", params, AJAX::CONTENT_TYPE::JSON)
params = to_json_for_add
url = "/api/2.0/asset_groups/#{group_id}/tags"
uri = AJAX.post(connection, url, params, AJAX::CONTENT_TYPE::JSON)
@id = uri.split('/').last.to_i
end
alias_method :add_to_asset_group, :add_to_group

private

def _to_json_for_add
def to_json_for_add
if @id == -1
json = {
'tag_name' => @name,
'tag_type' => @type,
'attributes' => [
{ 'tag_attribute_name' => 'SOURCE',
'tag_attribute_value' => @source }
],
}
json = { 'tag_name' => @name,
'tag_type' => @type,
'attributes' => [{ 'tag_attribute_name' => 'SOURCE',
'tag_attribute_value' => @source }] }
if @type == Tag::Type::Generic::CUSTOM
json['attributes'] << { 'tag_attribute_name' => 'COLOR', 'tag_attribute_value' => @color }
json['attributes'] << { 'tag_attribute_name' => 'COLOR',
'tag_attribute_value' => @color }
end
params = JSON.generate(json)
else
Expand Down
Loading

0 comments on commit 942401e

Please sign in to comment.