From bbab5a7e670bb4c3799334905e6d3086388ffbb6 Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Fri, 1 Sep 2017 14:16:56 -0700 Subject: [PATCH 01/11] cleanup for A files --- lib/nexpose/ajax.rb | 28 ++++++++++++--------------- lib/nexpose/alert.rb | 41 +++++++++++++++++++-------------------- lib/nexpose/api.rb | 6 +++--- lib/nexpose/asset.rb | 46 ++++++++++++++++++++++---------------------- 4 files changed, 58 insertions(+), 63 deletions(-) diff --git a/lib/nexpose/ajax.rb b/lib/nexpose/ajax.rb index 72703491..9660a869 100644 --- a/lib/nexpose/ajax.rb +++ b/lib/nexpose/ajax.rb @@ -15,7 +15,7 @@ module AJAX # Content type strings acceptect by Nexpose. # module CONTENT_TYPE - XML = 'text/xml; charset=UTF-8' + XML = 'text/xml; charset=UTF-8' JSON = 'application/json; charset-utf-8' FORM = 'application/x-www-form-urlencoded; charset=UTF-8' end @@ -192,8 +192,8 @@ def get_request_api_version(request) # Get an error message from the response body if the request url api version # is 2.1 or greater otherwise use the request body def get_error_message(request, response) - version = get_request_api_version(request) - data_request = use_response_error_message?(request, response) + version = get_request_api_version(request) + data_request = use_response_error_message?(request, response) return_response = (version >= 2.1 || data_request) (return_response && response.body) ? "response body: #{response.body}" : "request body: #{request.body}" end @@ -220,12 +220,10 @@ def use_response_error_message?(request, response) # @param [String] pref Preference key value to preserve. # def preserving_preference(nsc, pref) - begin - orig = get_rows(nsc, pref) - yield - ensure - set_rows(nsc, pref, orig) - end + orig = get_rows(nsc, pref) + yield + ensure + set_rows(nsc, pref, orig) end # Get a valid row preference value. @@ -251,10 +249,10 @@ def row_pref_of(val) end def get_rows(nsc, pref) - uri = '/data/user/preferences/all' + uri = '/data/user/preferences/all' pref_key = "#{pref}.rows" - resp = get(nsc, uri) - json = JSON.parse(resp) + resp = get(nsc, uri) + json = JSON.parse(resp) if json.key?(pref_key) rows = json[pref_key].to_i rows > 0 ? rows : 10 @@ -264,10 +262,8 @@ def get_rows(nsc, pref) end def set_rows(nsc, pref, value) - uri = '/data/user/preference' - params = { 'name' => "#{pref}.rows", - 'value' => value } - + uri = '/data/user/preference' + params = { 'name' => "#{pref}.rows", 'value' => value } form_post(nsc, uri, params) end diff --git a/lib/nexpose/alert.rb b/lib/nexpose/alert.rb index e0b7967b..817b0a4a 100644 --- a/lib/nexpose/alert.rb +++ b/lib/nexpose/alert.rb @@ -76,7 +76,7 @@ module Alert # load a particular site alert def self.load(nsc, site_id, alert_id) - uri = "/api/2.1/site_configurations/#{site_id}/alerts/#{alert_id}" + uri = "/api/2.1/site_configurations/#{site_id}/alerts/#{alert_id}" resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) unless resp.to_s == '' @@ -92,7 +92,7 @@ def self.load_alerts(alerts) # load a list of alerts for a given site def self.list_alerts(nsc, site_id) - uri = "/api/2.1/site_configurations/#{site_id}/alerts" + uri = "/api/2.1/site_configurations/#{site_id}/alerts" resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) data = JSON.parse(resp, symbolize_names: true) load_alerts(data) unless data.nil? @@ -120,7 +120,7 @@ def delete(nsc, site_id) def save(nsc, site_id) validate uri = "/api/2.1/site_configurations/#{site_id}/alerts" - id = AJAX.put(nsc, uri, self.to_json, AJAX::CONTENT_TYPE::JSON) + id = AJAX.put(nsc, uri, self.to_json, AJAX::CONTENT_TYPE::JSON) @id = id.to_i end @@ -130,12 +130,10 @@ def validate raise ArgumentError.new('Vuln filter is a required attribute.') unless @vuln_filter end - private - def self.create(hash) alert_type = hash[:alert_type] raise 'An alert must have an alert type' if alert_type.nil? - raise 'Alert name cannot be empty.' if !hash.has_key?(:name) || hash[:name].to_s == '' + raise 'Alert name cannot be empty.' if !hash.key?(:name) || hash[:name].to_s == '' raise 'SNMP and Syslog alerts must have a server defined' if ['SNMP', 'Syslog'].include?(alert_type) && hash[:server].to_s == '' case alert_type @@ -174,22 +172,23 @@ class SMTPAlert attr_accessor :recipients, :sender, :verbose def initialize(name, sender, server, recipients, enabled = 1, max_alerts = -1, verbose = 0) - unless recipients.is_a?(Array) && recipients.length > 0 + unless recipients.is_a?(Array) && !recipients.empty? raise 'An SMTP alert must contain an array of recipient emails with at least 1 recipient' end - recipients.each do |recipient| + + recipients.each do |recipient| unless recipient =~ /^.+@.+\..+$/ raise "Recipients must contain valid emails, #{recipient} has an invalid format" end end @alert_type = 'SMTP' - @name = name - @enabled = enabled + @name = name + @enabled = enabled @max_alerts = max_alerts - @sender = sender - @server = server - @verbose = verbose + @sender = sender + @server = server + @verbose = verbose @recipients = recipients.nil? ? [] : recipients end @@ -209,13 +208,12 @@ class SNMPAlert def initialize(name, community, server, enabled = 1, max_alerts = -1) raise 'SNMP alerts must have a community defined.' if community.nil? - @alert_type = 'SNMP' - @name = name - @enabled = enabled + @name = name + @enabled = enabled @max_alerts = max_alerts - @community = community - @server = server + @community = community + @server = server end end @@ -225,10 +223,11 @@ class SyslogAlert def initialize(name, server, enabled = 1, max_alerts = -1) @alert_type = 'Syslog' - @name = name - @enabled = enabled + @name = name + @enabled = enabled @max_alerts = max_alerts - @server = server + @server = server end end + end diff --git a/lib/nexpose/api.rb b/lib/nexpose/api.rb index 13572174..03faf636 100644 --- a/lib/nexpose/api.rb +++ b/lib/nexpose/api.rb @@ -22,7 +22,7 @@ class APIObject # def object_from_hash(nsc, hash) hash.each do |k, v| - next if k == :url # Do not store self-referential URL. + next if k == :url # Do not store self-referential URL. # Store resource URLs separately and create lazy accessors. if v.is_a?(Hash) && v.key?(:url) self.class.send(:define_method, k, proc { |conn = nsc| load_resource(conn, k, v[:url].gsub(/.*\/api/, '/api')) }) @@ -52,7 +52,7 @@ def object_from_hash(nsc, hash) # @return [Array[?]] Collection of "k" marshalled object. # def load_resource(nsc, k, url) - obj = class_from_string(k) + obj = class_from_string(k) resp = AJAX.get(nsc, url, AJAX::CONTENT_TYPE::JSON) hash = JSON.parse(resp, symbolize_names: true) if hash.is_a?(Array) @@ -85,7 +85,6 @@ def class_from_string(field) module TypedAccessor def typed_accessor(name, type) - # here we dynamically define accessor methods define_method(name) do instance_variable_get("@#{name}") @@ -100,4 +99,5 @@ def typed_accessor(name, type) end end end + end diff --git a/lib/nexpose/asset.rb b/lib/nexpose/asset.rb index 0865416d..f880ba19 100644 --- a/lib/nexpose/asset.rb +++ b/lib/nexpose/asset.rb @@ -42,7 +42,7 @@ class Asset < APIObject attr_accessor :unique_identifiers def initialize - @addresses = [] + @addresses = [] @host_names = [] end @@ -53,7 +53,7 @@ def initialize # @return [Asset] The requested asset, if found. # def self.load(nsc, id) - uri = "/api/2.1/assets/#{id}" + uri = "/api/2.1/assets/#{id}" resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) hash = JSON.parse(resp, symbolize_names: true) new.object_from_hash(nsc, hash) @@ -97,9 +97,9 @@ def to_h def <=>(other) c = port <=> other.port - return c unless c == 0 + return c unless c.zero? c = protocol <=> other.protocol - return c unless c == 0 + return c unless c.zero? name <=> other.name end @@ -114,27 +114,27 @@ def eql?(other) # Valid protocol values for a service endpoint. module Protocol # Internet Protocol - IP = 'IP' + IP = 'IP' # Internet Control Message Protocol ICMP = 'ICMP' # Internet Group Management Protocol IGMP = 'IGMP' # Gateway-to-Gateway Protocol - GGP = 'GGP' + GGP = 'GGP' # Transmission Control Protocol - TCP = 'TCP' + TCP = 'TCP' # PARC Universal Protocol - PUP = 'PUP' + PUP = 'PUP' # User Datagram Protocol - UDP = 'UDP' + UDP = 'UDP' # Internet Datagram Protocol - IDP = 'IDP' + IDP = 'IDP' # Encapsulating Security Payload - ESP = 'ESP' + ESP = 'ESP' # Network Disk Protocol - ND = 'ND' + ND = 'ND' # Raw Packet (or unknown) - RAW = 'RAW' + RAW = 'RAW' end end @@ -163,11 +163,11 @@ def to_h def <=>(other) c = name <=> other.name - return c unless c == 0 + return c unless c.zero? c = id <=> other.id - return c unless c == 0 + return c unless c.zero? c = full_name <=> other.full_name - return c unless c == 0 + return c unless c.zero? attributes <=> other.attributes end @@ -204,9 +204,9 @@ def to_h def <=>(other) c = name <=> other.name - return c unless c == 0 + return c unless c.zero? c = id <=> other.id - return c unless c == 0 + return c unless c.zero? attributes <=> other.attributes end @@ -248,11 +248,11 @@ def to_h def <=>(other) c = name <=> other.name - return c unless c == 0 + return c unless c.zero? c = size <=> other.size - return c unless c == 0 + return c unless c.zero? c = directory <=> other.directory - return c unless c == 0 + return c unless c.zero? attributes <=> other.attributes end @@ -274,7 +274,7 @@ class UniqueIdentifier < APIObject attr_reader :id def initialize(source = nil, id = nil) - @id = id + @id = id @source = source end @@ -285,7 +285,7 @@ def to_h def <=>(other) c = source <=> other.source - return c unless c == 0 + return c unless c.zero? id <=> other.id end From 32bde2022ccbe8c5febf922d2c1e56a3cc1cec41 Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Fri, 1 Sep 2017 14:36:06 -0700 Subject: [PATCH 02/11] cleanup for B,C files --- .rubocop.yml | 4 + lib/nexpose/blackout.rb | 20 ++--- lib/nexpose/common.rb | 179 ++++++++++++++++++-------------------- lib/nexpose/connection.rb | 18 ++-- lib/nexpose/console.rb | 18 ++-- 5 files changed, 114 insertions(+), 125 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index bfdd54f3..b1ef7054 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -29,3 +29,7 @@ Metrics/ModuleLength: Metrics/ClassLength: Max: 200 + +Metrics/MethodLength: + Max: 20 + diff --git a/lib/nexpose/blackout.rb b/lib/nexpose/blackout.rb index 5139e852..99629560 100644 --- a/lib/nexpose/blackout.rb +++ b/lib/nexpose/blackout.rb @@ -1,6 +1,6 @@ module Nexpose -# Constants useful across the Nexpose module. -# Configuration structure for blackouts. + # Constants useful across the Nexpose module. + # Configuration structure for blackouts. class Blackout < APIObject # Whether or not this blackout is enabled. attr_accessor :enabled @@ -14,7 +14,7 @@ class Blackout < APIObject # The amount of time, in minutes, a blackout period should last. attr_accessor :blackout_duration - def initialize(start, enabled=true, duration, type, interval) + def initialize(start, enabled = true, duration, type, interval) @blackout_start = start @enabled = enabled @blackout_duration = duration.to_i @@ -24,7 +24,6 @@ def initialize(start, enabled=true, duration, type, interval) def self.from_hash(hash) repeat_blackout_hash = hash[:repeat_blackout] - if repeat_blackout_hash.nil? type = 'daily' interval = 0 @@ -32,22 +31,15 @@ def self.from_hash(hash) type = repeat_blackout_hash[:type] interval = repeat_blackout_hash[:interval] end - new(hash[:start_date], hash[:enabled], hash[:blackout_duration], type, interval) end def to_h - blackout_hash = { - start_date: @blackout_start, - enabled: @enabled, - blackout_duration: @blackout_duration, - } - repeat_hash= { - type: @blackout_type, - interval: @blackout_interval - } + blackout_hash = { start_date: @blackout_start, enabled: @enabled, blackout_duration: @blackout_duration } + repeat_hash = { type: @blackout_type, interval: @blackout_interval } blackout_hash[:repeat_blackout] = repeat_hash blackout_hash end end + end diff --git a/lib/nexpose/common.rb b/lib/nexpose/common.rb index a5f7ef81..0cd424f0 100644 --- a/lib/nexpose/common.rb +++ b/lib/nexpose/common.rb @@ -2,7 +2,7 @@ module Nexpose # Constants useful across the Nexpose module. module Scope GLOBAL = 'global' - SILO = 'silo' + SILO = 'silo' end # Configuration structure for e-mail notification. @@ -49,11 +49,10 @@ class Email def initialize(to_all_authorized, send_to_owner_as, send_to_acl_as, send_as) @to_all_authorized = to_all_authorized - @send_to_owner_as = send_to_owner_as - @send_to_acl_as = send_to_acl_as - @send_as = send_as - - @recipients = [] + @send_to_owner_as = send_to_owner_as + @send_to_acl_as = send_to_acl_as + @send_as = send_as + @recipients = [] end def to_xml @@ -116,9 +115,9 @@ def initialize(start, scan_template_id, max_duration = nil) def as_xml xml = REXML::Element.new('AdHocSchedule') - xml.attributes['start'] = @start + xml.attributes['start'] = @start xml.attributes['maxDuration'] = @max_duration if @max_duration - xml.attributes['template'] = @scan_template_id + xml.attributes['template'] = @scan_template_id xml end @@ -170,10 +169,10 @@ class Schedule < APIObject # @param [Time] start def initialize(type, interval, start, enabled = true, scan_template_id = nil) - @type = type - @interval = interval - @start = start - @enabled = enabled + @type = type + @interval = interval + @start = start + @enabled = enabled @scan_template_id = scan_template_id end @@ -186,29 +185,28 @@ def self.from_hash(hash) else schedule = new(repeat_scan_hash[:type], repeat_scan_hash[:interval], start) end - schedule.enabled = hash[:enabled].nil? ? true : hash[:enabled] + schedule.enabled = hash[:enabled].nil? ? true : hash[:enabled] schedule.scan_template_id = hash[:scan_template_id] - schedule.start = Nexpose::ISO8601.to_time(hash[:start_date]) if hash[:start_date] - schedule.max_duration = hash[:maximum_scan_duration] if hash[:maximum_scan_duration] - schedule.not_valid_after = Nexpose::ISO8601.to_time(hash[:not_valid_after_date]) if hash[:not_valid_after_date] - schedule.timezone = hash[:time_zone] if hash[:time_zone] - schedule.next_run_time = hash[:next_run_time] if hash[:next_run_time] - schedule.console_start = Nexpose::ISO8601.to_time(hash[:console_start_date]) if hash[:console_start_date] + schedule.start = Nexpose::ISO8601.to_time(hash[:start_date]) if hash[:start_date] + schedule.max_duration = hash[:maximum_scan_duration] if hash[:maximum_scan_duration] + schedule.not_valid_after = Nexpose::ISO8601.to_time(hash[:not_valid_after_date]) if hash[:not_valid_after_date] + schedule.timezone = hash[:time_zone] if hash[:time_zone] + schedule.next_run_time = hash[:next_run_time] if hash[:next_run_time] + schedule.console_start = Nexpose::ISO8601.to_time(hash[:console_start_date]) if hash[:console_start_date] schedule.console_timezone = hash[:console_time_zone] if hash[:console_time_zone] unless repeat_scan_hash.nil? - schedule.type = repeat_scan_hash[:type] - schedule.interval = repeat_scan_hash[:interval] + schedule.type = repeat_scan_hash[:type] + schedule.interval = repeat_scan_hash[:interval] schedule.repeater_type = 'restart' if repeat_scan_hash[:on_repeat] == 'restart-scan' schedule.repeater_type = 'continue' if repeat_scan_hash[:on_repeat] == 'resume-scan' - - schedule.is_extended = repeat_scan_hash[:is_extended] if repeat_scan_hash[:is_extended] - schedule.hour = repeat_scan_hash[:hour] if repeat_scan_hash[:hour] - schedule.minute = repeat_scan_hash[:minute] if repeat_scan_hash[:minute] - schedule.date = repeat_scan_hash[:date] if repeat_scan_hash[:date] - schedule.day = repeat_scan_hash[:day] if repeat_scan_hash[:day] - schedule.occurrence = repeat_scan_hash[:occurrence] if repeat_scan_hash[:occurrence] - schedule.start_month = repeat_scan_hash[:start_month] if repeat_scan_hash[:start_month] + schedule.is_extended = repeat_scan_hash[:is_extended] if repeat_scan_hash[:is_extended] + schedule.hour = repeat_scan_hash[:hour] if repeat_scan_hash[:hour] + schedule.minute = repeat_scan_hash[:minute] if repeat_scan_hash[:minute] + schedule.date = repeat_scan_hash[:date] if repeat_scan_hash[:date] + schedule.day = repeat_scan_hash[:day] if repeat_scan_hash[:day] + schedule.occurrence = repeat_scan_hash[:occurrence] if repeat_scan_hash[:occurrence] + schedule.start_month = repeat_scan_hash[:start_month] if repeat_scan_hash[:start_month] end schedule @@ -220,28 +218,26 @@ def to_h scan_template_id: @scan_template_id, maximum_scan_duration: @max_duration } - schedule_hash[:start_date] = Nexpose::ISO8601.to_string(@start) if @start + schedule_hash[:start_date] = Nexpose::ISO8601.to_string(@start) if @start schedule_hash[:not_valid_after_date] = Nexpose::ISO8601.to_string(@not_valid_after) if @not_valid_after - schedule_hash[:time_zone] = @timezone if @timezone + schedule_hash[:time_zone] = @timezone if @timezone - unless (@type.nil? || @interval == 0) && !@is_extended + unless (@type.nil? || @interval.zero?) && !@is_extended repeat_scan_hash = { type: @type, interval: @interval } repeat_scan_hash[:on_repeat] = 'restart-scan' if @repeater_type == 'restart' repeat_scan_hash[:on_repeat] = 'resume-scan' if @repeater_type == 'continue' - if @is_extended repeat_scan_hash[:is_extended] = @is_extended - repeat_scan_hash[:hour] = @hour if @hour - repeat_scan_hash[:minute] = @minute if @minute - repeat_scan_hash[:date] = @date if @date - repeat_scan_hash[:day] = @day if @day - repeat_scan_hash[:occurrence] = @occurrence if @occurrence + repeat_scan_hash[:hour] = @hour if @hour + repeat_scan_hash[:minute] = @minute if @minute + repeat_scan_hash[:date] = @date if @date + repeat_scan_hash[:day] = @day if @day + repeat_scan_hash[:occurrence] = @occurrence if @occurrence repeat_scan_hash[:start_month] = @start_month if @start_month end - schedule_hash[:repeat_scan] = repeat_scan_hash end @@ -250,22 +246,22 @@ def to_h def as_xml xml = REXML::Element.new('Schedule') - xml.attributes['enabled'] = @enabled ? 1 : 0 - xml.attributes['type'] = @type - xml.attributes['interval'] = @interval - xml.attributes['start'] = @start if @start - xml.attributes['maxDuration'] = @max_duration if @max_duration + xml.attributes['enabled'] = @enabled ? 1 : 0 + xml.attributes['type'] = @type + xml.attributes['interval'] = @interval + xml.attributes['start'] = @start if @start + xml.attributes['maxDuration'] = @max_duration if @max_duration xml.attributes['notValidAfter'] = @not_valid_after if @not_valid_after - xml.attributes['repeaterType'] = @repeater_type if @repeater_type - xml.attributes['is_extended'] = @is_extended if @is_extended - xml.attributes['hour'] = @hour if @hour - xml.attributes['minute'] = @minute if @minute - xml.attributes['date'] = @date if @date - xml.attributes['day'] = @day if @day - xml.attributes['occurrence'] = @occurrence if @occurrence - xml.attributes['start_month'] = @start_month if @start_month - xml.attributes['timezone'] = @timezone if @timezone - xml.attributes['template'] = @scan_template_id if @scan_template_id + xml.attributes['repeaterType'] = @repeater_type if @repeater_type + xml.attributes['is_extended'] = @is_extended if @is_extended + xml.attributes['hour'] = @hour if @hour + xml.attributes['minute'] = @minute if @minute + xml.attributes['date'] = @date if @date + xml.attributes['day'] = @day if @day + xml.attributes['occurrence'] = @occurrence if @occurrence + xml.attributes['start_month'] = @start_month if @start_month + xml.attributes['timezone'] = @timezone if @timezone + xml.attributes['template'] = @scan_template_id if @scan_template_id xml end @@ -280,18 +276,18 @@ def self.parse(xml) xml.attributes['enabled'] != '0') # Optional parameters. - schedule.max_duration = xml.attributes['maxDuration'].to_i if xml.attributes['maxDuration'] - schedule.not_valid_after = xml.attributes['notValidAfter'] if xml.attributes['notValidAfter'] - schedule.repeater_type = xml.attributes['repeaterType'] if xml.attributes['repeaterType'] - schedule.is_extended = xml.attributes['is_extended'] if xml.attributes['is_extended'] - schedule.hour = xml.attributes['hour'] if xml.attributes['hour'] - schedule.minute = xml.attributes['minute'] if xml.attributes['minute'] - schedule.date = xml.attributes['date'] if xml.attributes['date'] - schedule.day = xml.attributes['day'] if xml.attributes['day'] - schedule.occurrence = xml.attributes['occurrence'] if xml.attributes['occurrence'] - schedule.start_month = xml.attributes['start_month'] if xml.attributes['start_month'] - schedule.timezone = xml.attributes['timezone'] if xml.attributes['timezone'] - schedule.next_run_time = xml.attributes['next_run_time'] if xml.attributes['next_run_time'] + schedule.max_duration = xml.attributes['maxDuration'].to_i if xml.attributes['maxDuration'] + schedule.not_valid_after = xml.attributes['notValidAfter'] if xml.attributes['notValidAfter'] + schedule.repeater_type = xml.attributes['repeaterType'] if xml.attributes['repeaterType'] + schedule.is_extended = xml.attributes['is_extended'] if xml.attributes['is_extended'] + schedule.hour = xml.attributes['hour'] if xml.attributes['hour'] + schedule.minute = xml.attributes['minute'] if xml.attributes['minute'] + schedule.date = xml.attributes['date'] if xml.attributes['date'] + schedule.day = xml.attributes['day'] if xml.attributes['day'] + schedule.occurrence = xml.attributes['occurrence'] if xml.attributes['occurrence'] + schedule.start_month = xml.attributes['start_month'] if xml.attributes['start_month'] + schedule.timezone = xml.attributes['timezone'] if xml.attributes['timezone'] + schedule.next_run_time = xml.attributes['next_run_time'] if xml.attributes['next_run_time'] schedule.scan_template_id = xml.attributes['template'] if xml.attributes['template'] schedule end @@ -300,11 +296,11 @@ def self.parse(xml) # may be used to create a Schedule. # module Type - DAILY = 'daily' - HOURLY = 'hourly' - WEEKLY = 'weekly' + DAILY = 'daily' + HOURLY = 'hourly' + WEEKLY = 'weekly' MONTHLY_DATE = 'monthly-date' - MONTHLY_DAY = 'monthly-day' + MONTHLY_DAY = 'monthly-day' end end @@ -337,40 +333,39 @@ def to_h state: state, city: city, zip: zip, - country: country - } + country: country } end # Create organization object from hash def self.create(hash) new do |org| - org.name = hash[:name] - org.url = hash[:url] + org.name = hash[:name] + org.url = hash[:url] org.primary_contact = hash[:primary_contact] - org.job_title = hash[:job_title] - org.email = hash[:email] - org.telephone = hash[:telephone] - org.address = hash[:address] - org.state = hash[:state] - org.city = hash[:city] - org.zip = hash[:zip] - org.country = hash[:country] + org.job_title = hash[:job_title] + org.email = hash[:email] + org.telephone = hash[:telephone] + org.address = hash[:address] + org.state = hash[:state] + org.city = hash[:city] + org.zip = hash[:zip] + org.country = hash[:country] end end def self.parse(xml) new do |org| - org.name = xml.attributes['name'] - org.url = xml.attributes['url'] + org.name = xml.attributes['name'] + org.url = xml.attributes['url'] org.primary_contact = xml.attributes['primaryContact'] - org.job_title = xml.attributes['jobTitle'] - org.email = xml.attributes['email'] - org.telephone = xml.attributes['telephone'] - org.address = xml.attributes['businessAddress'] - org.state = xml.attributes['state'] - org.city = xml.attributes['city'] - org.zip = xml.attributes['zip'] - org.country = xml.attributes['country'] + org.job_title = xml.attributes['jobTitle'] + org.email = xml.attributes['email'] + org.telephone = xml.attributes['telephone'] + org.address = xml.attributes['businessAddress'] + org.state = xml.attributes['state'] + org.city = xml.attributes['city'] + org.zip = xml.attributes['zip'] + org.country = xml.attributes['country'] end end diff --git a/lib/nexpose/connection.rb b/lib/nexpose/connection.rb index 48d36a93..13ec966f 100644 --- a/lib/nexpose/connection.rb +++ b/lib/nexpose/connection.rb @@ -97,17 +97,15 @@ def initialize(ip, user, pass, port = 3780, silo_id = nil, token = nil, trust_ce # Establish a new connection and Session ID def login - begin - login_hash = { 'sync-id' => 0, 'password' => @password, 'user-id' => @username, 'token' => @token } - login_hash['silo-id'] = @silo_id if @silo_id - r = execute(make_xml('LoginRequest', login_hash)) - if r.success - @session_id = r.sid - true - end - rescue APIError - raise AuthenticationFailed.new(r) + login_hash = { 'sync-id' => 0, 'password' => @password, 'user-id' => @username, 'token' => @token } + login_hash['silo-id'] = @silo_id if @silo_id + r = execute(make_xml('LoginRequest', login_hash)) + if r.success + @session_id = r.sid + true end + rescue APIError + raise AuthenticationFailed.new(r) end # Logout of the current connection diff --git a/lib/nexpose/console.rb b/lib/nexpose/console.rb index d2df5f3e..01079a1e 100644 --- a/lib/nexpose/console.rb +++ b/lib/nexpose/console.rb @@ -1,3 +1,4 @@ +# here uh what module Nexpose # Nexpose console configuration class. @@ -32,13 +33,12 @@ class Console # def initialize(xml) @xml = xml - - nsc = REXML::XPath.first(@xml, 'NeXposeSecurityConsole') - @scan_threads_limit = nsc.attributes['scanThreadsLimit'].to_i + nsc = REXML::XPath.first(@xml, 'NeXposeSecurityConsole') + @scan_threads_limit = nsc.attributes['scanThreadsLimit'].to_i @incremental_scan_results = nsc.attributes['realtimeIntegration'] == '1' - web_server = REXML::XPath.first(nsc, 'WebServer') - @session_timeout = web_server.attributes['sessionTimeout'].to_i + web_server = REXML::XPath.first(nsc, 'WebServer') + @session_timeout = web_server.attributes['sessionTimeout'].to_i end # Load existing Nexpose security console configuration. @@ -56,15 +56,15 @@ def self.load(connection) # @return [Boolean] true if configuration successfully saved. # def save(connection) - nsc = REXML::XPath.first(@xml, 'NeXposeSecurityConsole') - nsc.attributes['scanThreadsLimit'] = @scan_threads_limit.to_i + nsc = REXML::XPath.first(@xml, 'NeXposeSecurityConsole') + nsc.attributes['scanThreadsLimit'] = @scan_threads_limit.to_i nsc.attributes['realtimeIntegration'] = @incremental_scan_results ? '1' : '0' - web_server = REXML::XPath.first(nsc, 'WebServer') + web_server = REXML::XPath.first(nsc, 'WebServer') web_server.attributes['sessionTimeout'] = @session_timeout.to_i response = REXML::Document.new(Nexpose::AJAX.post(connection, '/data/admin/config/nsc', @xml)) - saved = REXML::XPath.first(response, 'SaveConfig') + saved = REXML::XPath.first(response, 'SaveConfig') saved.attributes['success'] == '1' end end From 580432e9f05f6a59f969e8ef79dc3521ddf5410c Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Fri, 1 Sep 2017 16:54:40 -0700 Subject: [PATCH 03/11] formatting all D files --- lib/nexpose/dag.rb | 4 +- lib/nexpose/data_table.rb | 20 +++--- lib/nexpose/device.rb | 69 +++++++++---------- lib/nexpose/discovery.rb | 138 +++++++++++++++++++------------------- 4 files changed, 114 insertions(+), 117 deletions(-) diff --git a/lib/nexpose/dag.rb b/lib/nexpose/dag.rb index 636baa85..6860aed7 100644 --- a/lib/nexpose/dag.rb +++ b/lib/nexpose/dag.rb @@ -32,8 +32,8 @@ def save(nsc) admins = nsc.users.select { |u| u.is_admin }.map { |u| u.id } @users.reject! { |id| admins.member? id } params = @id ? { 'entityid' => @id, 'mode' => 'edit' } : { 'entityid' => false, 'mode' => false } - uri = AJAX.parameterize_uri('/data/assetGroup/saveAssetGroup', params) - data = JSON.parse(AJAX.post(nsc, uri, _to_entity_details, AJAX::CONTENT_TYPE::JSON)) + uri = AJAX.parameterize_uri('/data/assetGroup/saveAssetGroup', params) + data = JSON.parse(AJAX.post(nsc, uri, _to_entity_details, AJAX::CONTENT_TYPE::JSON)) data['response'] == 'success.' end diff --git a/lib/nexpose/data_table.rb b/lib/nexpose/data_table.rb index b0ab8810..7e325da8 100644 --- a/lib/nexpose/data_table.rb +++ b/lib/nexpose/data_table.rb @@ -32,30 +32,26 @@ module DataTable # 'siteID' => site_id }) # def _get_json_table(console, address, parameters = {}, page_size = 500, records = nil, post = true) - parameters['dir'] = 'DESC' + parameters['dir'] = 'DESC' parameters['startIndex'] = -1 - parameters['results'] = -1 - + parameters['results'] = -1 if post request = lambda { |p| AJAX.form_post(console, address, p) } else request = lambda { |p| AJAX.get(console, address.dup, AJAX::CONTENT_TYPE::JSON, p) } end - response = request.(parameters) - data = JSON.parse(response) - + response = request.call(parameters) + data = JSON.parse(response) # Don't attept to grab more records than there are. total = data['totalRecords'] - return [] if total == 0 + return [] if total.zero? total = records.nil? ? total : [records, total].min - - rows = [] + rows = [] parameters['results'] = page_size while rows.length < total parameters['startIndex'] = rows.length - - data = JSON.parse(request.(parameters)) + data = JSON.parse(request.call(parameters)) rows.concat data['records'] end rows @@ -80,7 +76,7 @@ def _get_dyn_table(console, address, payload = nil) response = REXML::Document.new(response) headers = _dyn_headers(response) - rows = _dyn_rows(response) + rows = _dyn_rows(response) rows.map { |row| Hash[headers.zip(row)] } end diff --git a/lib/nexpose/device.rb b/lib/nexpose/device.rb index c83daf18..2401d536 100644 --- a/lib/nexpose/device.rb +++ b/lib/nexpose/device.rb @@ -18,16 +18,18 @@ def find_device_by_address(address, site_id = nil) r = execute(make_xml('SiteDeviceListingRequest', { 'site-id' => site_id })) if r.success device = REXML::XPath.first(r.res, "SiteDeviceListingResponse/SiteDevices/device[@address='#{address}']") - return Device.new(device.attributes['id'].to_i, - device.attributes['address'], - device.parent.attributes['site-id'], - device.attributes['riskfactor'].to_f, - device.attributes['riskscore'].to_f) if device + if device + return Device.new(device.attributes['id'].to_i, + device.attributes['address'], + device.parent.attributes['site-id'], + device.attributes['riskfactor'].to_f, + device.attributes['riskscore'].to_f) + end end nil end - alias_method :find_asset_by_address, :find_device_by_address + alias find_asset_by_address find_device_by_address # Retrieve a list of all of the assets in a site. # @@ -57,10 +59,10 @@ def list_site_devices(site_id = nil) devices end - alias_method :devices, :list_site_devices - alias_method :list_devices, :list_site_devices - alias_method :assets, :list_site_devices - alias_method :list_assets, :list_site_devices + alias devices list_site_devices + alias list_devices list_site_devices + alias assets list_site_devices + alias list_assets list_site_devices # Get a list of all assets currently associated with a group. # @@ -89,9 +91,9 @@ def list_device_vulns(dev_id) json.map { |vuln| VulnFinding.new(vuln) } end - alias_method :list_asset_vulns, :list_device_vulns - alias_method :asset_vulns, :list_device_vulns - alias_method :device_vulns, :list_device_vulns + alias list_asset_vulns list_device_vulns + alias asset_vulns list_device_vulns + alias device_vulns list_device_vulns # Retrieve a list of assets which completed in a given scan. If called # during a scan, this method returns currently completed assets. A @@ -129,7 +131,7 @@ def delete_device(device_id) r.success end - alias_method :delete_asset, :delete_device + alias delete_asset delete_device # Retrieve the scan history for an asset. # Note: This is not optimized for querying many assets. @@ -174,11 +176,11 @@ class Device attr_reader :site_id def initialize(id, address, site_id, risk_factor = 1.0, risk_score = 0.0) - @id = id.to_i - @address = address - @site_id = site_id.to_i + @id = id.to_i + @address = address + @site_id = site_id.to_i @risk_factor = risk_factor.to_f - @risk_score = risk_score.to_f + @risk_score = risk_score.to_f end end @@ -220,13 +222,13 @@ def operating_system # object. def self.parse_json(json) new do - @id = json['assetID'].to_i - @ip = json['ipAddress'] + @id = json['assetID'].to_i + @ip = json['ipAddress'] @host_name = json['hostName'] - @os = json['operatingSystem'] - @vulns = json['vulnerabilityCount'] - @status = json['scanStatusTranslation'].downcase.to_sym - @duration = json['duration'] + @os = json['operatingSystem'] + @vulns = json['vulnerabilityCount'] + @status = json['scanStatusTranslation'].downcase.to_sym + @duration = json['duration'] end end end @@ -236,7 +238,6 @@ def self.parse_json(json) class IncompleteAsset < CompletedAsset end - # Summary object of a scan for a particular asset. # class AssetScan @@ -268,15 +269,15 @@ def initialize(&block) def self.parse_json(json) new do - @asset_id = json['assetID'].to_i - @scan_id = json['scanID'].to_i - @site_id = json['siteID'].to_i - @ip = json['ipAddress'] - @host_name = json['hostname'] - @os = json['operatingSystem'] - @vulns = json['vulnCount'] - @end_time = Time.at(json['completed'].to_i / 1000) - @site_name = json['siteName'] + @asset_id = json['assetID'].to_i + @scan_id = json['scanID'].to_i + @site_id = json['siteID'].to_i + @ip = json['ipAddress'] + @host_name = json['hostname'] + @os = json['operatingSystem'] + @vulns = json['vulnCount'] + @end_time = Time.at(json['completed'].to_i / 1000) + @site_name = json['siteName'] @engine_name = json['scanEngineName'] end end diff --git a/lib/nexpose/discovery.rb b/lib/nexpose/discovery.rb index 0888ea43..9e1e4864 100644 --- a/lib/nexpose/discovery.rb +++ b/lib/nexpose/discovery.rb @@ -6,22 +6,22 @@ class Connection # discovery of assets, including whether or not connections are active. # def list_discovery_connections - xml = make_xml('DiscoveryConnectionListingRequest') - response = execute(xml, '1.2') + xml = make_xml('DiscoveryConnectionListingRequest') + response = execute(xml, '1.2') connections = [] response.res.elements.each('DiscoveryConnectionListingResponse/DiscoveryConnectionSummary') do |conn| connections << DiscoveryConnection.parse(conn) end connections end - alias_method :discovery_connections, :list_discovery_connections + alias discovery_connections list_discovery_connections # Delete an existing connection to a target used for dynamic discovery of assets. # # @param [Fixnum] id ID of an existing discovery connection. # def delete_discovery_connection(id) - xml = make_xml('DiscoveryConnectionDeleteRequest', { 'id' => id }) + xml = make_xml('DiscoveryConnectionDeleteRequest', { 'id' => id }) response = execute(xml, '1.2') response.success end @@ -32,22 +32,22 @@ class DiscoveryConnection < APIObject module CollectionMethod DIRECTORY_WATCHER = 'DIRECTORY_WATCHER' - SYSLOG = 'SYSLOG' + SYSLOG = 'SYSLOG' end module EventSource INFOBLOX_TRINZIC = 'INFOBLOX_TRINZIC' - MICROSOFT_DHCP = 'MICROSOFT_DHCP' + MICROSOFT_DHCP = 'MICROSOFT_DHCP' end module Protocol - HTTP = 'HTTP' - HTTPS = 'HTTPS' - LDAP = 'LDAP' - LDAPS = 'LDAPS' + HTTP = 'HTTP' + HTTPS = 'HTTPS' + LDAP = 'LDAP' + LDAPS = 'LDAPS' SERVICE_PROXY = 'SERVICE_PROXY' - TCP = 'TCP' - UDP = 'UDP' + TCP = 'TCP' + UDP = 'UDP' end module Type @@ -56,51 +56,37 @@ module Type ACTIVESYNC = 'ACTIVESYNC' ACTIVESYNC_POWERSHELL = 'ACTIVESYNC_POWERSHELL' ACTIVESYNC_OFFICE365 = 'ACTIVESYNC_OFFICE365' - DHCP_SERVICE = 'DHCP_SERVICE' + DHCP_SERVICE = 'DHCP_SERVICE' end # A unique identifier for this connection. attr_accessor :id - # A unique name for this connection. attr_accessor :name - # Type of discovery connection attr_accessor :type - # The IP address or fully qualified domain name of the server. attr_accessor :address - # The engine ID to use for this connection. attr_accessor :engine_id - # A user name that can be used to log into the server. attr_accessor :user - # The password to use when connecting with the defined user. attr_accessor :password - # The protocol used for connecting to the server. One of DiscoveryConnection::Protocol attr_accessor :protocol - # The port used for connecting to the server. A valid port from 1 to 65535. attr_accessor :port - # The hostname of the exchange server to connect for exchange powershell connections attr_accessor :exchange_hostname - # The exchange username to connect for exchange powershell connections attr_accessor :exchange_username - # The exchange password to connect for exchange powershell connections attr_accessor :exchange_password - # The collection method (e.g. for DHCP discovery connections) attr_accessor :collection_method - # The event source (e.g. for DHCP discovery connections) attr_accessor :event_source - # Whether or not the connection is active. # Discovery is only possible when the connection is active. attr_accessor :status @@ -114,10 +100,13 @@ module Type # @param [String] password Password for credentials on this connection. # def initialize(name = nil, address = nil, user = nil, password = nil) - @name, @address, @user, @password = name, address, user, password - @type = nil # for backwards compatibilitly, at some point should set this to Type::VSPHERE - @id = -1 - @port = 443 + @name = name + @address = address + @user = user + @password = password + @type = nil # For backwards compatibilitly, at some point should set this to Type::VSPHERE + @id = -1 + @port = 443 @protocol = Protocol::HTTPS end @@ -155,7 +144,6 @@ def update(nsc) # def save(nsc) @id == -1 ? create(nsc) : update(nsc) - @id end @@ -181,7 +169,7 @@ def discover(nsc, criteria = nil) # @param [Connection] nsc Connection to a console. # def connect(nsc) - xml = nsc.make_xml('DiscoveryConnectionConnectRequest', { 'id' => id }) + xml = nsc.make_xml('DiscoveryConnectionConnectRequest', { 'id' => id }) response = nsc.execute(xml, '1.2') response.success end @@ -221,10 +209,10 @@ def self.parse(xml) conn = new(xml.attributes['name'], xml.attributes['address'], xml.attributes['user-name']) - conn.id = xml.attributes['id'].to_i - conn.protocol = xml.attributes['protocol'] - conn.port = xml.attributes['port'].to_i - conn.status = xml.attributes['connection-status'] + conn.id = xml.attributes['id'].to_i + conn.protocol = xml.attributes['protocol'] + conn.port = xml.attributes['port'].to_i + conn.status = xml.attributes['connection-status'] conn.engine_id = xml.attributes['engine-id'].to_i conn end @@ -234,10 +222,11 @@ def to_json end def to_h - { id: id, + { + id: id, name: name, type: type - # TODO Add remaining instance fields, once it is introduced in resource object + # TODO: Add remaining instance fields, once it is introduced in resource object } end @@ -246,10 +235,8 @@ def ==(other) end def eql?(other) - id.eql?(other.id) && - name.eql?(other.name) && - type.eql?(other.type) - # TODO Add remaining instance fields, once it is introduced in resource object + id.eql?(other.id) && name.eql?(other.name) && type.eql?(other.type) + # TODO: Add remaining instance fields, once it is introduced in resource object end # Override of filter criterion to account for proper JSON naming. @@ -306,7 +293,7 @@ class DiscoveredAsset attr_accessor :status def initialize(&block) - instance_eval &block if block_given? + instance_eval(&block) if block_given? end def on? @@ -315,14 +302,14 @@ def on? def self.parse(json) new do |asset| - asset.ip = json['IPAddress'] - asset.os = json['OSName'] - asset.name = json['assetDiscoveryName'] - asset.cluster = json['cluster'] + asset.ip = json['IPAddress'] + asset.os = json['OSName'] + asset.name = json['assetDiscoveryName'] + asset.cluster = json['cluster'] asset.datacenter = json['datacenter'] - asset.host = json['host'] - asset.status = json['powerStatus'] - asset.pool = json['resourcePool'] + asset.host = json['host'] + asset.status = json['powerStatus'] + asset.pool = json['resourcePool'] end end end @@ -338,13 +325,17 @@ class MobileDiscoveryConnection < DiscoveryConnection # @param [String] password Password for credentials on this connection. # def initialize(name, protocol, address, user, password = nil) - @name, @protocol, @address, @user, @password = name, protocol, address, user, password - @type = Type::ACTIVESYNC - @id = -1 - @port = 443 # port not used for mobile connection + @name = name + @protocol = protocol + @address = address + @user = user + @password = password + @type = Type::ACTIVESYNC + @id = -1 + @port = 443 # port not used for mobile connection end end - + class MobilePowershellDiscoveryConnection < DiscoveryConnection # Create a new Mobile Powershell discovery connection. # @@ -358,12 +349,17 @@ class MobilePowershellDiscoveryConnection < DiscoveryConnection # @param [String] exchange_password Exchange password for exchange credentials on this connection. # def initialize(name, address, user, password, exchange_hostname, exchange_username, exchange_password) - @name, @address, @user, @password = name, address, user, password - @protocol = Protocol::HTTPS - @exchange_hostname, @exchange_username, @exchange_password = exchange_hostname, exchange_username, exchange_password - @type = Type::ACTIVESYNC_POWERSHELL - @id = -1 - @port = 443 # port not used for mobile connection + @name = name + @address = address + @user = user + @password = password + @protocol = Protocol::HTTPS + @exchange_hostname = exchange_hostname + @exchange_username = exchange_username + @exchange_password = exchange_password + @type = Type::ACTIVESYNC_POWERSHELL + @id = -1 + @port = 443 # Port not used for mobile connection end end @@ -379,13 +375,17 @@ class MobileOffice365DiscoveryConnection < DiscoveryConnection # @param [String] exchange_password Exchange password for exchange credentials on this connection. # def initialize(name, address, user, password, exchange_username, exchange_password) - @name, @address, @user, @password = name, address, user, password - @protocol = Protocol::HTTPS - @exchange_hostname = '' # nexpose will set to office365 server - @exchange_username, @exchange_password = exchange_username, exchange_password - @type = Type::ACTIVESYNC_OFFICE365 - @id = -1 - @port = 443 # port not used for mobile connection + @name = name + @address = address + @user = user + @password = password + @protocol = Protocol::HTTPS + @exchange_hostname = '' # Nexpose will set to office365 server + @exchange_username = exchange_username + @exchange_password = exchange_password + @type = Type::ACTIVESYNC_OFFICE365 + @id = -1 + @port = 443 # Port not used for mobile connection end end end From 89d41f76aa9a94ea2764100a4935f4b8c9b3e230 Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Fri, 1 Sep 2017 17:02:00 -0700 Subject: [PATCH 04/11] formatting all E files --- lib/nexpose/engine.rb | 43 +++++++++++++++++++++-------------------- lib/nexpose/error.rb | 12 +++++++----- lib/nexpose/external.rb | 37 ++++++++++++++++++++--------------- 3 files changed, 50 insertions(+), 42 deletions(-) diff --git a/lib/nexpose/engine.rb b/lib/nexpose/engine.rb index 1dc08889..72625cb6 100644 --- a/lib/nexpose/engine.rb +++ b/lib/nexpose/engine.rb @@ -10,8 +10,7 @@ class Connection # @return [Boolean] true if engine successfully deleted. # def delete_engine(engine_id, scope = 'silo') - xml = make_xml('EngineDeleteRequest', - {'engine-id' => engine_id, 'scope' => scope}) + xml = make_xml('EngineDeleteRequest', { 'engine-id' => engine_id, 'scope' => scope }) response = execute(xml, '1.2') response.success end @@ -27,9 +26,9 @@ def delete_engine(engine_id, scope = 'silo') # @return [Boolean] true if the connection is successfully reversed. # def reverse_engine_connection(engine_id) - uri = "/api/2.1/engine/#{engine_id}/reverseConnection" + uri = "/api/2.1/engine/#{engine_id}/reverseConnection" response = AJAX.put(self, uri) - response.eql?("true") + response.eql?('true') end # Kicks off an update on a single engine. @@ -54,8 +53,8 @@ def update_engine(engine_id) # each active scan on the engine. # def engine_activity(engine_id) - xml = make_xml('EngineActivityRequest', {'engine-id' => engine_id}) - r = execute(xml) + xml = make_xml('EngineActivityRequest', { 'engine-id' => engine_id }) + r = execute(xml) arr = [] if r.success r.res.elements.each('//ScanSummary') do |scan_event| @@ -72,7 +71,7 @@ def engine_activity(engine_id) # def list_engines response = execute(make_xml('EngineListingRequest')) - arr = [] + arr = [] if response.success response.res.elements.each('//EngineSummary') do |engine| arr << EngineSummary.new(engine.attributes['id'].to_i, @@ -86,7 +85,7 @@ def list_engines arr end - alias_method :engines, :list_engines + alias engines list_engines end # Object representing the current details of a scan engine attached to the @@ -110,12 +109,12 @@ class EngineSummary attr_reader :scope def initialize(id, name, address, port, status, scope = 'silo') - @id = id - @name = name + @id = id + @name = name @address = address - @port = port - @status = status - @scope = scope + @port = port + @status = status + @scope = scope end end @@ -143,13 +142,13 @@ class Engine attr_accessor :sites def initialize(address, name = nil, port = 40814) - @id = -1 + @id = -1 @address = address - @name = name - @name ||= address - @port = port - @scope = 'silo' - @sites = [] + @name = name + @name ||= address + @port = port + @scope = 'silo' + @sites = [] end def self.load(connection, id) @@ -163,12 +162,14 @@ def self.load(connection, id) engine = Engine.new(config.attributes['address'], config.attributes['name'], config.attributes['port']) - engine.id = config.attributes['id'] - engine.scope = config.attributes['scope'] if config.attributes['scope'] + engine.id = config.attributes['id'] + engine.scope = config.attributes['scope'] if config.attributes['scope'] engine.priority = config.attributes['priority'] if config.attributes['priority'] + config.elements.each('Site') do |site| engine.sites << SiteSummary.new(site.attributes['id'], site.attributes['name']) end + return engine end end diff --git a/lib/nexpose/error.rb b/lib/nexpose/error.rb index 32946546..86c2f41c 100644 --- a/lib/nexpose/error.rb +++ b/lib/nexpose/error.rb @@ -1,12 +1,13 @@ module Nexpose + class APIError < ::RuntimeError attr_accessor :req, :reason attr_reader :code def initialize(req, reason = '', code = 400) - @req = req + @req = req @reason = reason - @code = code + @code = code end def to_s @@ -16,15 +17,16 @@ def to_s class AuthenticationFailed < APIError def initialize(req) - @req = req - @reason = "Login Failed" + @req = req + @reason = 'Login Failed' end end class PermissionError < APIError def initialize(req) - @req = req + @req = req @reason = 'User does not have permission to perform this action.' end end + end diff --git a/lib/nexpose/external.rb b/lib/nexpose/external.rb index 1dc35570..0247d8f5 100644 --- a/lib/nexpose/external.rb +++ b/lib/nexpose/external.rb @@ -27,10 +27,10 @@ def import_assets(site_id, assets) # @return [Array[ImportResult]] collection of import results. # def import_assets_from_json(site_id, json) - uri = "/api/2.1/sites/#{site_id}/assets" + uri = "/api/2.1/sites/#{site_id}/assets" # Wait up to 5 minutes for a response. resp = AJAX.post(self, uri, json, AJAX::CONTENT_TYPE::JSON, 300) - arr = JSON.parse(resp, symbolize_names: true) + arr = JSON.parse(resp, symbolize_names: true) arr.map { |e| External::ImportResult.new.object_from_hash(self, e) } end end @@ -87,15 +87,15 @@ class Asset attr_accessor :vulnerabilities def initialize - @aliases = [] - @software = [] - @services = [] - @attributes = [] - @users = [] - @groups = [] - @files = [] + @aliases = [] + @software = [] + @services = [] + @attributes = [] + @users = [] + @groups = [] + @files = [] @unique_identifiers = [] - @vulnerabilities = [] + @vulnerabilities = [] end def to_json @@ -123,10 +123,10 @@ def to_h # Valid host types for an asset. module HostType - GUEST = 'GUEST' + GUEST = 'GUEST' HYPERVISOR = 'HYPERVISOR' - PHYSICAL = 'PHYSICAL' - MOBILE = 'MOBILE' + PHYSICAL = 'PHYSICAL' + MOBILE = 'MOBILE' end end @@ -143,7 +143,9 @@ class Service attr_accessor :vulnerabilities def initialize(port, protocol = Protocol::RAW, name = nil) - @port, @protocol, @name = port, protocol, name + @port = port + @protocol = protocol + @name = name @vulnerabilities = [] end @@ -169,7 +171,10 @@ class VulnerabilityCheck attr_accessor :proof def initialize(vuln_id, status = Status::EXPLOITED, proof = nil, key = nil) - @vuln_id, @status, @proof, @key = vuln_id, status, proof, key + @vuln_id = vuln_id + @status = status + @proof = proof + @key = key end def to_h @@ -185,7 +190,7 @@ module Status EXPLOITED = 'vulnerable-exploited' # Vulnerable because the service or software version is associated with # a known vulnerability. - VERSION = 'vulnerable-version' + VERSION = 'vulnerable-version' # A potential vulnerability. POTENTIAL = 'potential' end From ced4a0a854e99a15324952345fc4ea9c83c49338 Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Tue, 5 Sep 2017 10:42:11 -0700 Subject: [PATCH 05/11] cleanup f,g,j files --- lib/nexpose/filter.rb | 103 ++++++++++++++++----------------- lib/nexpose/global_blackout.rb | 13 ++--- lib/nexpose/global_settings.rb | 5 +- lib/nexpose/group.rb | 44 ++++++++------ lib/nexpose/json_serializer.rb | 18 ++---- 5 files changed, 88 insertions(+), 95 deletions(-) diff --git a/lib/nexpose/filter.rb b/lib/nexpose/filter.rb index da2ac6a1..45e9c838 100644 --- a/lib/nexpose/filter.rb +++ b/lib/nexpose/filter.rb @@ -14,7 +14,7 @@ class Connection # def filter(field, operator, value = '') criterion = Criterion.new(field, operator, value) - criteria = Criteria.new(criterion) + criteria = Criteria.new(criterion) search(criteria) end @@ -34,9 +34,7 @@ def filter(field, operator, value = '') # @return [Array[FilteredAsset]] List of matching assets. # def search(criteria) - results = DataTable._get_json_table(self, - '/data/asset/filterAssets', - criteria._to_payload) + results = DataTable._get_json_table(self, '/data/asset/filterAssets', criteria._to_payload) results.map { |a| FilteredAsset.new(a) } end end @@ -173,32 +171,32 @@ module Field # List of acceptable operators. Not all fields accept all operators. # module Operator - CONTAINS = 'CONTAINS' - NOT_CONTAINS = 'NOT_CONTAINS' - IS = 'IS' - IS_NOT = 'IS_NOT' - ARE = 'ARE' - IN = 'IN' - NOT_IN = 'NOT_IN' - IN_RANGE = 'IN_RANGE' - NOT_IN_RANGE = 'NOT_IN_RANGE' - STARTS_WITH = 'STARTS_WITH' - ENDS_WITH = 'ENDS_WITH' - ON_OR_BEFORE = 'ON_OR_BEFORE' - ON_OR_AFTER = 'ON_OR_AFTER' - BETWEEN = 'BETWEEN' - EARLIER_THAN = 'EARLIER_THAN' + ARE = 'ARE' + BETWEEN = 'BETWEEN' + CONTAINS = 'CONTAINS' + DO_NOT_INCLUDE = 'DO_NOT_INCLUDE' + EARLIER_THAN = 'EARLIER_THAN' + ENDS_WITH = 'ENDS_WITH' + GREATER_THAN = 'GREATER_THAN' + IN = 'IN' + INCLUDE = 'INCLUDE' + IN_RANGE = 'IN_RANGE' + IS = 'IS' + IS_APPLIED = 'IS_APPLIED' + IS_EMPTY = 'IS_EMPTY' + IS_NOT = 'IS_NOT' + IS_NOT_APPLIED = 'IS_NOT_APPLIED' + IS_NOT_EMPTY = 'IS_NOT_EMPTY' + LESS_THAN = 'LESS_THAN' + LIKE = 'LIKE' + NOT_CONTAINS = 'NOT_CONTAINS' + NOT_IN = 'NOT_IN' + NOT_IN_RANGE = 'NOT_IN_RANGE' + NOT_LIKE = 'NOT_LIKE' + ON_OR_AFTER = 'ON_OR_AFTER' + ON_OR_BEFORE = 'ON_OR_BEFORE' + STARTS_WITH = 'STARTS_WITH' WITHIN_THE_LAST = 'WITHIN_THE_LAST' - GREATER_THAN = 'GREATER_THAN' - LESS_THAN = 'LESS_THAN' - IS_EMPTY = 'IS_EMPTY' - IS_NOT_EMPTY = 'IS_NOT_EMPTY' - INCLUDE = 'INCLUDE' - DO_NOT_INCLUDE = 'DO_NOT_INCLUDE' - IS_APPLIED = 'IS_APPLIED' - IS_NOT_APPLIED = 'IS_NOT_APPLIED' - LIKE = 'LIKE' - NOT_LIKE = 'NOT_LIKE' end # Specialized values used by certain search fields @@ -206,36 +204,36 @@ module Operator module Value # Constants for filtering on access complexity. module AccessComplexity - LOW = 'L' + LOW = 'L' MEDIUM = 'M' - HIGH = 'H' + HIGH = 'H' end # Constants for filtering on access vector. module AccessVector - LOCAL = 'L' + LOCAL = 'L' ADJACENT = 'A' - NETWORK = 'N' + NETWORK = 'N' end # Constants for filtering on whether authentication is required. module AuthenticationRequired - NONE = 'N' - SINGLE = 'S' + NONE = 'N' + SINGLE = 'S' MULTIPLE = 'M' end # Constants for filtering on CVSS impact. module CVSSImpact - NONE = 'N' - PARTIAL = 'P' + NONE = 'N' + PARTIAL = 'P' COMPLETE = 'C' end # Constants for filtering on host type. module HostType - UNKNOWN = '0' - VIRTUAL = '1' + UNKNOWN = '0' + VIRTUAL = '1' HYPERVISOR = '2' BARE_METAL = '3' end @@ -263,15 +261,15 @@ module ScanDate # Constants for filtering on vulnerability validations. module ValidatedVulnerability NOT_PRESENT = 1 - PRESENT = 0 + PRESENT = 0 end # Constants for filtering on vulnerability exposure. module VulnerabilityExposure - MALWARE = 'type:"malware_type", name:"malwarekit"' + MALWARE = 'type:"malware_type", name:"malwarekit"' # TODO: A problem in Nexpose causes these values to not be constant. METASPLOIT = 'type:"exploit_source_type", name:"2"' - DATABASE = 'type:"exploit_source_type", name:"1"' + DATABASE = 'type:"exploit_source_type", name:"1"' end end end @@ -288,7 +286,8 @@ class Criterion attr_accessor :value def initialize(field, operator, value = '') - @field, @operator = field.upcase, operator.upcase + @field = field.upcase + @operator = operator.upcase if value.is_a? Array @value = value.map(&:to_s) else @@ -384,17 +383,17 @@ class FilteredAsset attr_reader :last_scan def initialize(json) - @id = json['assetID'] - @ip = json['assetIP'] - @name = json['assetName'] - @os = json['assetOSName'] + @id = json['assetID'] + @ip = json['assetIP'] + @name = json['assetName'] + @os = json['assetOSName'] @exploit_count = json['exploitCount'].to_i @malware_count = json['malwareCount'].to_i - @vuln_count = json['vulnCount'].to_i - @risk_score = json['riskScore'].to_f - @site_ids = json['sitePermissions'].map { |site| site['siteID'] } - @site_id = @site_ids.first - @last_scan = Time.at(json['lastScanDate'].to_i / 1000) + @vuln_count = json['vulnCount'].to_i + @risk_score = json['riskScore'].to_f + @site_ids = json['sitePermissions'].map { |site| site['siteID'] } + @site_id = @site_ids.first + @last_scan = Time.at(json['lastScanDate'].to_i / 1000) end end end diff --git a/lib/nexpose/global_blackout.rb b/lib/nexpose/global_blackout.rb index 1bca28ad..ae776b31 100644 --- a/lib/nexpose/global_blackout.rb +++ b/lib/nexpose/global_blackout.rb @@ -18,8 +18,7 @@ def save(nsc) def to_h { - blackouts: - (@blackout || []).map { |blackout| blackout.to_h } + blackouts: (@blackout || []).map { |blackout| blackout.to_h } } end @@ -32,11 +31,11 @@ def self.json_initializer(data) end def self.load(nsc) - uri = '/api/2.1/silo_blackout/' - resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) - hash = JSON.parse(resp, symbolize_names: true) - blackout = self.json_initializer(hash).deserialize(hash) - blackout.blackout = (hash[:blackouts] || []).map { |blackout| Nexpose::Blackout.from_hash(blackout) } + uri = '/api/2.1/silo_blackout/' + resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) + hash = JSON.parse(resp, symbolize_names: true) + blackout = self.json_initializer(hash).deserialize(hash) + blackout.blackout = (hash[:blackouts] || []).map { |bout| Nexpose::Blackout.from_hash(bout) } blackout end end diff --git a/lib/nexpose/global_settings.rb b/lib/nexpose/global_settings.rb index d89f6da2..8d4592d7 100644 --- a/lib/nexpose/global_settings.rb +++ b/lib/nexpose/global_settings.rb @@ -19,9 +19,8 @@ class GlobalSettings # Private constructor. See #load method for retrieving a settings object. # def initialize(xml) - @xml = xml - - @asset_linking = parse_asset_linking_from_xml(xml) + @xml = xml + @asset_linking = parse_asset_linking_from_xml(xml) @asset_exclusions = HostOrIP.parse(xml) @control_scanning = parse_control_scanning_from_xml(xml) end diff --git a/lib/nexpose/group.rb b/lib/nexpose/group.rb index fe2aabcd..cef4b135 100644 --- a/lib/nexpose/group.rb +++ b/lib/nexpose/group.rb @@ -10,11 +10,11 @@ class Connection # @return [Boolean] Whether group deletion succeeded. # def delete_asset_group(id) - r = execute(make_xml('AssetGroupDeleteRequest', {'group-id' => id})) + r = execute(make_xml('AssetGroupDeleteRequest', { 'group-id' => id })) r.success end - alias_method :delete_group, :delete_asset_group + alias delete_group delete_asset_group # Retrieve an array of all asset groups the user is authorized to view or # manage. @@ -23,7 +23,6 @@ def delete_asset_group(id) # def list_asset_groups r = execute(make_xml('AssetGroupListingRequest')) - groups = [] if r.success r.res.elements.each('AssetGroupListingResponse/AssetGroupSummary') do |group| @@ -37,8 +36,8 @@ def list_asset_groups groups end - alias_method :groups, :list_asset_groups - alias_method :asset_groups, :list_asset_groups + alias groups list_asset_groups + alias asset_groups list_asset_groups end # Summary value object for asset group information. @@ -47,7 +46,11 @@ class AssetGroupSummary attr_reader :id, :name, :description, :risk_score, :dynamic def initialize(id, name, desc, risk, dynamic) - @id, @name, @description, @risk_score, @dynamic = id, name, desc, risk, dynamic + @id = id + @name = name + @description = desc + @risk_score = risk + @dynamic = dynamic end def dynamic? @@ -68,17 +71,20 @@ def delete(connection) class AssetGroup < AssetGroupSummary include Sanitize - attr_accessor :name, :description, :id , :tags + attr_accessor :name, :description, :id, :tags # Array[Device] of devices associated with this asset group. attr_accessor :assets - alias :devices :assets - alias :devices= :assets= + alias devices assets + alias devices= assets= def initialize(name, desc, id = -1, risk = 0.0) - @name, @description, @id, @risk_score = name, desc, id, risk - @assets = [] - @tags = [] + @name = name + @description = desc + @id = id + @risk_score = risk + @assets = [] + @tags = [] end def save(connection) @@ -86,7 +92,7 @@ def save(connection) xml << to_xml xml << '' res = connection.execute(xml) - @id = res.attributes['group-id'].to_i if res.success and @id < 1 + @id = res.attributes['group-id'].to_i if res.success && @id < 1 end # Generate an XML representation of this group configuration @@ -95,8 +101,8 @@ def save(connection) # def as_xml xml = REXML::Element.new('AssetGroup') - xml.attributes['id'] = @id - xml.attributes['name'] = @name + xml.attributes['id'] = @id + xml.attributes['name'] = @name xml.attributes['description'] = @description if @description && !@description.empty? @@ -106,7 +112,7 @@ def as_xml end elem = REXML::Element.new('Devices') - @assets.each { |a| elem.add_element('device', {'id' => a.id}) } + @assets.each { |a| elem.add_element('device', { 'id' => a.id }) } xml.add_element(elem) unless tags.empty? @@ -134,8 +140,8 @@ def to_xml # @return [Hash] Hash of site ID to Scan launch information for each scan. # def rescan_assets(connection) - sites_ids = @assets.map { |d| d.site_id }.uniq - scans = {} + scans = {} + sites_ids = @assets.map(&:site_id).uniq sites_ids.each do |site_id| to_scan = @assets.select { |d| d.site_id == site_id } scans[site_id] = connection.scan_devices(to_scan) @@ -153,7 +159,7 @@ def rescan_assets(connection) # def self.load(connection, id) xml = %() - r = APIRequest.execute(connection.url, xml) + r = APIRequest.execute(connection.url, xml) parse(r.res) end diff --git a/lib/nexpose/json_serializer.rb b/lib/nexpose/json_serializer.rb index 18020ce3..e46350e8 100644 --- a/lib/nexpose/json_serializer.rb +++ b/lib/nexpose/json_serializer.rb @@ -6,13 +6,11 @@ def deserialize(data) data.each do |key, value| if respond_to?(key) property = value - if value.respond_to? :each obj = resolve_type(key) - unless obj.nil? if value.is_a?(Array) - property = value.map { |dv| ((dv.respond_to? :each) ? create_object(obj, dv).deserialize(dv): dv) } + property = value.map { |dv| ((dv.respond_to? :each) ? create_object(obj, dv).deserialize(dv) : dv) } else property = create_object(obj, value).deserialize(value) end @@ -20,20 +18,15 @@ def deserialize(data) elsif value.is_a?(String) && value.match(/^\d{8}T\d{6}\.\d{3}/) property = ISO8601.to_time(value) end - instance_variable_set("@#{key}", property) end end - self end - def serialize() + def serialize hash = to_hash(Hash.new) - - unless hash.nil? - JSON.generate(hash) - end + JSON.generate(hash) unless hash.nil? end def to_hash(hash) @@ -41,7 +34,6 @@ def to_hash(hash) value = self.instance_variable_get(m) hash[m.to_s.delete('@')] = do_hash(value) end - hash end @@ -51,12 +43,10 @@ def do_hash(obj) if obj.is_a?(Array) obj = obj.map do |el| do_hash(el) - end elsif obj.class.included_modules.include? JsonSerializer obj = obj.to_hash(Hash.new) end - obj end @@ -89,4 +79,4 @@ def normalize_field(field) class_name end end -end \ No newline at end of file +end From 7e4d66e2092b63d24f833bc2df92840bc2726202 Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Tue, 5 Sep 2017 10:58:13 -0700 Subject: [PATCH 06/11] cleanup m,p files --- lib/nexpose/maint.rb | 17 +++---- lib/nexpose/manage.rb | 4 +- lib/nexpose/multi_tenant_user.rb | 84 ++++++++++++++++---------------- lib/nexpose/password_policy.rb | 28 +++++------ lib/nexpose/pool.rb | 11 +++-- 5 files changed, 72 insertions(+), 72 deletions(-) diff --git a/lib/nexpose/maint.rb b/lib/nexpose/maint.rb index 27520ff3..7da7bba0 100644 --- a/lib/nexpose/maint.rb +++ b/lib/nexpose/maint.rb @@ -46,11 +46,10 @@ def backup(platform_independent = false, description = nil) # def db_maintenance(clean_up = false, compress = false, reindex = false) return unless compress || clean_up || reindex - parameters = { 'cmd' => 'startMaintenance', - 'targetTask' => 'dbMaintenance' } - parameters['cleanup'] = 1 if clean_up + parameters = { 'cmd' => 'startMaintenance', 'targetTask' => 'dbMaintenance' } + parameters['cleanup'] = 1 if clean_up parameters['compress'] = 1 if compress - parameters['reindex'] = 1 if reindex + parameters['reindex'] = 1 if reindex xml = AJAX.form_post(self, '/admin/global/maintenance/maintCmd.txml', parameters) if !!(xml =~ /succeded="true"/) _maintenance_restart @@ -85,12 +84,12 @@ class Backup attr_reader :size def initialize(name, date, description, version, independent, size) - @name = name - @date = date - @description = description - @version = version + @name = name + @date = date + @description = description + @version = version @platform_independent = independent - @size = size + @size = size end # Restore this backup to the Nexpose console. diff --git a/lib/nexpose/manage.rb b/lib/nexpose/manage.rb index fd99ea7a..0de39f01 100644 --- a/lib/nexpose/manage.rb +++ b/lib/nexpose/manage.rb @@ -47,9 +47,9 @@ def system_information # Includes Product, Content, and Java versions. # def engine_versions - info = console_command('version engines') + info = console_command('version engines') versions = [] - engines = info.sub('VERSION INFORMATION\n', '').split(/\n\n/) + engines = info.sub('VERSION INFORMATION\n', '').split(/\n\n/) engines.each do |eng| engdata = {} eng.split(/\n/).each do |kv| diff --git a/lib/nexpose/multi_tenant_user.rb b/lib/nexpose/multi_tenant_user.rb index 064b9708..009f1a48 100644 --- a/lib/nexpose/multi_tenant_user.rb +++ b/lib/nexpose/multi_tenant_user.rb @@ -17,14 +17,14 @@ def list_silo_users end arr end - alias_method :silo_users, :list_silo_users + alias silo_users list_silo_users # Delete the specified silo user # # @return Whether or not the delete request succeeded. # def delete_silo_user(user_id) - r = execute(make_xml('MultiTenantUserDeleteRequest', {'user-id' => user_id}), '1.2') + r = execute(make_xml('MultiTenantUserDeleteRequest', { 'user-id' => user_id }), '1.2') r.success end end @@ -42,21 +42,21 @@ class MultiTenantUserSummary attr_reader :locked def initialize(&block) - instance_eval &block if block_given? + instance_eval(&block) if block_given? end def self.parse(xml) new do - @id = xml.attributes['id'].to_i - @full_name = xml.attributes['full-name'] - @user_name = xml.attributes['user-name'] - @email = xml.attributes['email'] - @superuser = xml.attributes['superuser'].to_s.chomp.eql?('true') - @enabled = xml.attributes['enabled'].to_s.chomp.eql?('true') + @id = xml.attributes['id'].to_i + @full_name = xml.attributes['full-name'] + @user_name = xml.attributes['user-name'] + @email = xml.attributes['email'] + @superuser = xml.attributes['superuser'].to_s.chomp.eql?('true') + @enabled = xml.attributes['enabled'].to_s.chomp.eql?('true') @auth_module = xml.attributes['auth-module'] @auth_source = xml.attributes['auth-source'] - @silo_count = xml.attributes['silo-count'].to_i - @locked = xml.attributes['locked'].to_s.chomp.eql?('true') + @silo_count = xml.attributes['silo-count'].to_i + @locked = xml.attributes['locked'].to_s.chomp.eql?('true') end end end @@ -73,13 +73,13 @@ class MultiTenantUser attr_accessor :silo_access def initialize(&block) - instance_eval &block if block_given? + instance_eval(&block) if block_given? @silo_access = Array(@silo_access) end def save(connection) - if (@id) + if @id update(connection) else create(connection) @@ -112,14 +112,14 @@ def create(connection) def as_xml xml = REXML::Element.new('MultiTenantUserConfig') - xml.add_attributes({'id' => @id, - 'full-name' => @full_name, - 'user-name' => @user_name, - 'authsrcid' => @auth_source_id, - 'email' => @email, - 'password' => @password, - 'superuser' => @superuser, - 'enabled' => @enabled}) + xml.add_attributes({ 'id' => @id, + 'full-name' => @full_name, + 'user-name' => @user_name, + 'authsrcid' => @auth_source_id, + 'email' => @email, + 'password' => @password, + 'superuser' => @superuser, + 'enabled' => @enabled }) siloaccesses = xml.add_element('SiloAccesses') @silo_access.each { |silo_access| siloaccesses.add_element(silo_access.as_xml) } xml @@ -135,20 +135,20 @@ def to_xml def self.parse(xml) new do |user| - user.id = xml.attributes['id'].to_i - user.full_name = xml.attributes['full-name'] - user.user_name = xml.attributes['user-name'] - user.email = xml.attributes['email'] - user.superuser = xml.attributes['superuser'].to_s.chomp.eql?('true') - user.enabled = xml.attributes['enabled'].to_s.chomp.eql?('true') + user.id = xml.attributes['id'].to_i + user.full_name = xml.attributes['full-name'] + user.user_name = xml.attributes['user-name'] + user.email = xml.attributes['email'] + user.superuser = xml.attributes['superuser'].to_s.chomp.eql?('true') + user.enabled = xml.attributes['enabled'].to_s.chomp.eql?('true') user.auth_source_id = xml.attributes['authsrcid'].to_i - user.silo_access = [] + user.silo_access = [] xml.elements.each('SiloAccesses/SiloAccess') { |access| user.silo_access << SiloAccess.parse(access) } end end def self.load(connection, user_id) - r = connection.execute(connection.make_xml('MultiTenantUserConfigRequest', {'user-id' => user_id}), '1.2') + r = connection.execute(connection.make_xml('MultiTenantUserConfigRequest', { 'user-id' => user_id }), '1.2') if r.success r.res.elements.each('MultiTenantUserConfigResponse/MultiTenantUserConfig') do |config| @@ -169,30 +169,30 @@ class SiloAccess attr_accessor :groups def initialize(&block) - instance_eval &block if block_given? + instance_eval(&block) if block_given? @sites = Array(@sites) @groups = Array(@groups) end def as_xml xml = REXML::Element.new('SiloAccess') - xml.add_attributes({'all-groups' => @all_groups, - 'all-sites' => @all_sites, - 'role-name' => @role_name, - 'silo-id' => @silo_id, - 'default-silo' => @default}) + xml.add_attributes({ 'all-groups' => @all_groups, + 'all-sites' => @all_sites, + 'role-name' => @role_name, + 'silo-id' => @silo_id, + 'default-silo' => @default }) unless @groups.empty? groups = xml.add_element('AllowedGroups') @groups.each do |group| - groups.add_element('AllowedGroup', {'id' => group}) + groups.add_element('AllowedGroup', { 'id' => group }) end end unless @sites.empty? sites = xml.add_element('AllowedSites') @sites.each do |site| - sites.add_element('AllowedSite', {'id' => site}) + sites.add_element('AllowedSite', { 'id' => site }) end end @@ -206,11 +206,11 @@ def to_xml def self.parse(xml) new do |access| access.all_groups = xml.attributes['all-groups'].to_s.chomp.eql?('true') - access.all_sites = xml.attributes['all-sites'].to_s.chomp.eql?('true') - access.role_name = xml.attributes['role-name'] - access.silo_id = xml.attributes['silo-id'] - access.default = xml.attributes['default-silo'].to_s.chomp.eql?('true') - access.sites = [] + access.all_sites = xml.attributes['all-sites'].to_s.chomp.eql?('true') + access.role_name = xml.attributes['role-name'] + access.silo_id = xml.attributes['silo-id'] + access.default = xml.attributes['default-silo'].to_s.chomp.eql?('true') + access.sites = [] xml.elements.each('AllowedSites/AllowedSite') { |site| access.sites << site.attributes['id'].to_i } access.groups = [] xml.elements.each('AllowedGroups/AllowedGroup') { |group| access.groups << group.attributes['id'].to_i } diff --git a/lib/nexpose/password_policy.rb b/lib/nexpose/password_policy.rb index 148d406c..5c0c1666 100644 --- a/lib/nexpose/password_policy.rb +++ b/lib/nexpose/password_policy.rb @@ -11,12 +11,12 @@ class PasswordPolicy < APIObject attr_accessor :expiration_days def initialize(policy_name:, min_length:, max_length:, special_chars:, capitals:, digits:, expiration_days: 0) - @policy_name = policy_name.to_s - @min_length = min_length.to_i - @max_length = max_length.to_i - @special_chars = special_chars.to_i - @capitals = capitals.to_i - @digits = digits.to_i + @policy_name = policy_name.to_s + @min_length = min_length.to_i + @max_length = max_length.to_i + @special_chars = special_chars.to_i + @capitals = capitals.to_i + @digits = digits.to_i @expiration_days = expiration_days.to_i end @@ -32,13 +32,13 @@ def self.from_hash(hash) def to_h { - policyName: @policy_name, - minLength: @min_length, - maxLength: @max_length, - specialChars: @special_chars, - capitals: @capitals, - digits: @digits, - expirationDays: @expiration_days + policyName: @policy_name, + minLength: @min_length, + maxLength: @max_length, + specialChars: @special_chars, + capitals: @capitals, + digits: @digits, + expirationDays: @expiration_days } end @@ -52,7 +52,7 @@ def save(nsc) end def self.load(nsc) - uri = '/api/2.1/password_policy/' + uri = '/api/2.1/password_policy/' resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) hash = JSON.parse(resp, symbolize_names: true) self.from_hash(hash) diff --git a/lib/nexpose/pool.rb b/lib/nexpose/pool.rb index 4405a1e0..eb47d611 100644 --- a/lib/nexpose/pool.rb +++ b/lib/nexpose/pool.rb @@ -21,7 +21,7 @@ def list_engine_pools arr end - alias_method :engine_pools, :list_engine_pools + alias engine_pools list_engine_pools end # A summary of an engine pool. @@ -36,8 +36,8 @@ class EnginePoolSummary attr_reader :scope def initialize(id, name, scope = 'silo') - @id = id.to_i - @name = name + @id = id.to_i + @name = name @scope = scope end @@ -74,7 +74,9 @@ class EnginePool attr_accessor :engines def initialize(name, scope = 'silo', id = -1) - @name, @scope, @id = name, scope, id.to_i + @name = name + @scope = scope + @id = id.to_i @engines = [] end @@ -100,7 +102,6 @@ def self.load(connection, name, scope = 'silo') xml = %() xml << %() xml << '' - r = connection.execute(xml, '1.2') if r.success r.res.elements.each('EnginePoolDetailsResponse/EnginePool') do |pool| From fbf66c0a1a4b8901b9901e2e9dbfcdb343d36671 Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Tue, 5 Sep 2017 11:10:32 -0700 Subject: [PATCH 07/11] cleanup r files --- lib/nexpose/report.rb | 64 +++++++++--------- lib/nexpose/report_template.rb | 35 +++++----- lib/nexpose/role.rb | 119 ++++++++++++++++++--------------- 3 files changed, 111 insertions(+), 107 deletions(-) diff --git a/lib/nexpose/report.rb b/lib/nexpose/report.rb index 913a038f..953abba4 100644 --- a/lib/nexpose/report.rb +++ b/lib/nexpose/report.rb @@ -19,7 +19,7 @@ def list_reports reports end - alias_method :reports, :list_reports + alias reports list_reports # Generate a new report using the specified report definition. def generate_report(report_id, wait = false) @@ -38,7 +38,7 @@ def generate_report(report_id, wait = false) return summary unless summary.status == 'Started' sleep 5 so_far += 5 - if so_far % 60 == 0 + if (so_far % 60).zero? puts "Still waiting. Current status: #{summary.status}" end end @@ -101,13 +101,13 @@ class ReportConfigSummary attr_reader :scope def initialize(config_id, name, template_id, status, generated_on, uri, scope) - @config_id = config_id.to_i - @name = name - @template_id = template_id - @status = status + @config_id = config_id.to_i + @name = name + @template_id = template_id + @status = status @generated_on = generated_on - @uri = uri - @scope = scope + @uri = uri + @scope = scope end def self.parse(xml) @@ -138,11 +138,11 @@ class ReportSummary attr_reader :uri def initialize(id, config_id, status, generated_on, uri) - @id = id - @config_id = config_id.to_i - @status = status + @id = id + @config_id = config_id.to_i + @status = status @generated_on = generated_on - @uri = uri + @uri = uri end # Delete this report. @@ -194,11 +194,11 @@ class AdhocReportConfig def initialize(template_id, format, site_id = nil, owner = nil, time_zone = nil) @template_id = template_id - @format = format - @owner = owner - @time_zone = time_zone + @format = format + @owner = owner + @time_zone = time_zone - @filters = [] + @filters = [] @filters << Filter.new('site', site_id) if site_id end @@ -289,15 +289,14 @@ class ReportConfig < AdhocReportConfig # Construct a basic ReportConfig object. def initialize(name, template_id, format, id = -1, owner = nil, time_zone = nil) - @name = name + @name = name @template_id = template_id - @format = format - @id = id - @owner = owner - @time_zone = time_zone - - @filters = [] - @users = [] + @format = format + @id = id + @owner = owner + @time_zone = time_zone + @filters = [] + @users = [] end # Retrieve the configuration for an existing report definition. @@ -306,7 +305,7 @@ def self.load(connection, report_config_id) ReportConfig.parse(connection.execute(xml)) end - alias_method :get, :load + alias get load # Build and save a report configuration against the specified site using # the supplied type and format. @@ -436,11 +435,8 @@ def to_xml %() end - def ==(object) - object.equal?(self) || - (object.instance_of?(self.class) && - object.type == @type && - object.id == @id) + def ==(other) + other.equal?(self) || (other.instance_of?(self.class) && other.type == @type && other.id == @id) end def self.parse(xml) @@ -466,8 +462,8 @@ class Frequency def initialize(after_scan, scheduled, schedule = nil) @after_scan = after_scan - @scheduled = scheduled - @schedule = schedule + @scheduled = scheduled + @schedule = schedule end def to_xml @@ -610,9 +606,9 @@ def self.parse(xml) xml.elements.each('//credentials') do |creds| credential = ExportCredential.new(creds.text) # The following attributes may not exist. - credential.user_id = creds.attributes['userid'] + credential.user_id = creds.attributes['userid'] credential.password = creds.attributes['password'] - credential.realm = creds.attributes['realm'] + credential.realm = creds.attributes['realm'] return credential end nil diff --git a/lib/nexpose/report_template.rb b/lib/nexpose/report_template.rb index 8f3a85f1..18661665 100644 --- a/lib/nexpose/report_template.rb +++ b/lib/nexpose/report_template.rb @@ -19,7 +19,7 @@ def list_report_templates templates end - alias_method :report_templates, :list_report_templates + alias report_templates list_report_templates # Deletes an existing, custom report template. # Cannot delete built-in templates. @@ -53,11 +53,11 @@ class ReportTemplateSummary attr_reader :description def initialize(id, name, type, scope, built_in, description) - @id = id - @name = name - @type = type - @scope = scope - @built_in = built_in + @id = id + @name = name + @type = type + @scope = scope + @built_in = built_in @description = description end @@ -109,19 +109,18 @@ class ReportTemplate attr_accessor :attributes # Display asset names with IPs. attr_accessor :show_asset_names - alias :show_device_names :show_asset_names - alias :show_device_names= :show_asset_names= + alias show_device_names show_asset_names + alias show_device_names= show_asset_names= def initialize(name, type = 'document', id = -1, scope = 'silo', built_in = false) - @name = name - @type = type - @id = id - @scope = scope - @built_in = built_in - - @sections = [] - @properties = {} - @attributes = [] + @name = name + @type = type + @id = id + @scope = scope + @built_in = built_in + @sections = [] + @properties = {} + @attributes = [] @show_asset_names = false end @@ -219,7 +218,7 @@ class Section attr_accessor :properties def initialize(name) - @name = name + @name = name @properties = {} end diff --git a/lib/nexpose/role.rb b/lib/nexpose/role.rb index 74221f04..5b0c5e5d 100644 --- a/lib/nexpose/role.rb +++ b/lib/nexpose/role.rb @@ -4,44 +4,44 @@ module Nexpose module Privilege module Global - CREATE_REPORTS = 'CreateReports' - CONFIGURE_GLOBAL_SETTINGS = 'ConfigureGlobalSettings' - MANAGE_SITES = 'ManageSites' - MANAGE_ASSET_GROUPS = 'ManageAssetGroups' + CREATE_REPORTS = 'CreateReports' + CONFIGURE_GLOBAL_SETTINGS = 'ConfigureGlobalSettings' + MANAGE_SITES = 'ManageSites' + MANAGE_ASSET_GROUPS = 'ManageAssetGroups' MANAGE_DYNAMIC_ASSET_GROUPS = 'ManageDynamicAssetGroups' - MANAGE_SCAN_TEMPLATES = 'ManageScanTemplates' - MANAGE_REPORT_TEMPLATES = 'ManageReportTemplates' + MANAGE_SCAN_TEMPLATES = 'ManageScanTemplates' + MANAGE_REPORT_TEMPLATES = 'ManageReportTemplates' GENERATE_RESTRICTED_REPORTS = 'GenerateRestrictedReports' - MANAGE_SCAN_ENGINES = 'ManageScanEngines' - SUBMIT_VULN_EXCEPTIONS = 'SubmitVulnExceptions' - APPROVE_VULN_EXCEPTIONS = 'ApproveVulnExceptions' - DELETE_VULN_EXCEPTIONS = 'DeleteVulnExceptions' - CREATE_TICKETS = 'CreateTickets' - CLOSE_TICKETS = 'CloseTickets' - TICKET_ASSIGNEE = 'TicketAssignee' - ADD_USERS_TO_SITE = 'AddUsersToSite' - ADD_USERS_TO_GROUP = 'AddUsersToGroup' - ADD_USERS_TO_REPORT = 'AddUsersToReport' - MANAGE_POLICIES = 'ManagePolicies' - MANAGE_TAGS = 'ManageTags' + MANAGE_SCAN_ENGINES = 'ManageScanEngines' + SUBMIT_VULN_EXCEPTIONS = 'SubmitVulnExceptions' + APPROVE_VULN_EXCEPTIONS = 'ApproveVulnExceptions' + DELETE_VULN_EXCEPTIONS = 'DeleteVulnExceptions' + CREATE_TICKETS = 'CreateTickets' + CLOSE_TICKETS = 'CloseTickets' + TICKET_ASSIGNEE = 'TicketAssignee' + ADD_USERS_TO_SITE = 'AddUsersToSite' + ADD_USERS_TO_GROUP = 'AddUsersToGroup' + ADD_USERS_TO_REPORT = 'AddUsersToReport' + MANAGE_POLICIES = 'ManagePolicies' + MANAGE_TAGS = 'ManageTags' end module Site - VIEW_ASSET_DATA = 'ViewAssetData' # NOTE Duplicated between Site and AssetGroup - CONFIGURE_ALERTS = 'ConfigureAlerts' - CONFIGURE_CREDENTIALS = 'ConfigureCredentials' - CONFIGURE_ENGINES = 'ConfigureEngines' + VIEW_ASSET_DATA = 'ViewAssetData' # NOTE Duplicated between Site and AssetGroup + CONFIGURE_ALERTS = 'ConfigureAlerts' + CONFIGURE_CREDENTIALS = 'ConfigureCredentials' + CONFIGURE_ENGINES = 'ConfigureEngines' CONFIGURE_SCAN_TEMPLATES = 'ConfigureScanTemplates' CONFIGURE_SCHEDULE_SCANS = 'ConfigureScheduleScans' - CONFIGURE_SITE_SETTINGS = 'ConfigureSiteSettings' - CONFIGURE_TARGETS = 'ConfigureTargets' - MANUAL_SCANS = 'ManualScans' - PURGE_DATA = 'PurgeData' + CONFIGURE_SITE_SETTINGS = 'ConfigureSiteSettings' + CONFIGURE_TARGETS = 'ConfigureTargets' + MANUAL_SCANS = 'ManualScans' + PURGE_DATA = 'PurgeData' end module AssetGroup CONFIGURE_ASSETS = 'ConfigureAssets' - VIEW_ASSET_DATA = 'ViewAssetData' # NOTE Duplicated between Site and AssetGroup + VIEW_ASSET_DATA = 'ViewAssetData' # NOTE Duplicated between Site and AssetGroup end end @@ -51,27 +51,27 @@ class Connection # Returns a summary list of all roles. # def role_listing - xml = make_xml('RoleListingRequest') - r = execute(xml, '1.2') + xml = make_xml('RoleListingRequest') + r = execute(xml, '1.2') roles = [] if r.success r.res.elements.each('RoleListingResponse/RoleSummary') do |summary| - roles << RoleSummary::parse(summary) + roles << RoleSummary.parse(summary) end end roles end - alias_method :roles, :role_listing + alias roles role_listing def role_delete(role, scope = Scope::SILO) xml = make_xml('RoleDeleteRequest') - xml.add_element('Role', {'name' => role, 'scope' => scope}) + xml.add_element('Role', { 'name' => role, 'scope' => scope }) response = execute(xml, '1.2') response.success end - alias_method :delete_role, :role_delete + alias delete_role role_delete end # Role summary object encapsulating information about a role. @@ -98,7 +98,12 @@ class RoleSummary attr_accessor :scope def initialize(name, full_name, id, description, enabled = true, scope = Scope::SILO) - @name, @full_name, @id, @description, @enabled, @scope = name, full_name, id.to_i, description, enabled, scope + @name = name + @full_name = full_name + @id = id.to_i + @description = description + @enabled = enabled + @scope = scope end def self.parse(xml) @@ -116,12 +121,12 @@ class Role < RoleSummary # Constants, mapping UI terms to role names expected by API. - GLOBAL_ADMINISTRATOR = 'global-admin' - ASSET_OWNER = 'system-admin' + GLOBAL_ADMINISTRATOR = 'global-admin' + ASSET_OWNER = 'system-admin' CONTROLS_INSIGHT_ONLY = 'controls-insight-only' - SECURITY_MANAGER = 'security-manager' - SITE_OWNER = 'site-admin' - USER = 'user' + SECURITY_MANAGER = 'security-manager' + SITE_OWNER = 'site-admin' + USER = 'user' # Array of all privileges which are enabled for this role. # Note: Although the underlying XML has different requirements, this only checks for presence. @@ -133,7 +138,11 @@ class Role < RoleSummary attr_accessor :existing def initialize(name, full_name, id = -1, enabled = true, scope = Scope::SILO) - @name, @full_name, @id, @enabled, @scope = name, full_name, id.to_i, enabled, scope + @name = name + @full_name = full_name + @id = id.to_i + @enabled = enabled + @scope = scope @privileges = [] end @@ -147,7 +156,7 @@ def initialize(name, full_name, id = -1, enabled = true, scope = Scope::SILO) # def self.load(nsc, name, scope = Scope::SILO) xml = nsc.make_xml('RoleDetailsRequest') - xml.add_element('Role', {'name' => name, 'scope' => scope}) + xml.add_element('Role', { 'name' => name, 'scope' => scope }) response = APIRequest.execute(nsc.url, xml, '1.2') if response.success @@ -156,7 +165,7 @@ def self.load(nsc, name, scope = Scope::SILO) end end - alias_method :get, :load + alias get load # Create or save a Role to the Nexpose console. # @@ -170,9 +179,9 @@ def save(nsc) end xml.add_element(as_xml) - response = APIRequest.execute(nsc.url, xml, '1.2') - xml = REXML::XPath.first(response.res, 'RoleCreateResponse') - @id = xml.attributes['id'].to_i unless @existing + response = APIRequest.execute(nsc.url, xml, '1.2') + xml = REXML::XPath.first(response.res, 'RoleCreateResponse') + @id = xml.attributes['id'].to_i unless @existing @existing = true response.success end @@ -186,9 +195,9 @@ def save(nsc) # @return [Role] requested role. # def self.copy(nsc, name, scope = Scope::SILO) - role = load(nsc, name, scope) - role.name = role.full_name = nil - role.id = -1 + role = load(nsc, name, scope) + role.name = role.full_name = nil + role.id = -1 role.existing = false role end @@ -230,29 +239,29 @@ def to_xml def as_xml xml = REXML::Element.new('Role') - xml.add_attributes({'name' => @name, 'full-name' => @full_name, 'enabled' => enabled , 'scope' => @scope}) + xml.add_attributes({ 'name' => @name, 'full-name' => @full_name, 'enabled' => enabled, 'scope' => @scope }) xml.add_attribute('id', @id) if @id > 0 xml.add_element('Description').text = @description site_privileges = xml.add_element('SitePrivileges') - Privilege::Site::constants.each do |field| + Privilege::Site.constants.each do |field| as_s = Privilege::Site.const_get(field) enabled = privileges.member? as_s - site_privileges.add_element( as_s, {'enabled' => enabled}) + site_privileges.add_element(as_s, { 'enabled' => enabled }) end asset_group_privileges = xml.add_element('AssetGroupPrivileges') - Privilege::AssetGroup::constants.each do |field| + Privilege::AssetGroup.constants.each do |field| as_s = Privilege::AssetGroup.const_get(field) enabled = privileges.member? as_s - asset_group_privileges.add_element( as_s, {'enabled' => enabled}) + asset_group_privileges.add_element(as_s, { 'enabled' => enabled }) end global_privileges = xml.add_element('GlobalPrivileges') - Privilege::Global::constants.each do |field| + Privilege::Global.constants.each do |field| as_s = Privilege::Global.const_get(field) enabled = privileges.member? as_s - global_privileges.add_element( as_s, {'enabled' => enabled}) + global_privileges.add_element(as_s, { 'enabled' => enabled }) end xml From abe688d6b7adca98adfd72fa6b9b2a5d56d6a9eb Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Tue, 5 Sep 2017 13:37:09 -0700 Subject: [PATCH 08/11] cleanup s files --- lib/nexpose/scan.rb | 137 +++++++++------- lib/nexpose/scan_template.rb | 34 ++-- lib/nexpose/scheduled_backup.rb | 16 +- lib/nexpose/scheduled_maintenance.rb | 18 +-- lib/nexpose/shared_credential.rb | 63 ++++---- lib/nexpose/shared_secret.rb | 10 +- lib/nexpose/silo.rb | 134 ++++++++-------- lib/nexpose/silo_profile.rb | 97 ++++++------ lib/nexpose/site.rb | 224 ++++++++++++--------------- lib/nexpose/site_credentials.rb | 32 ++-- 10 files changed, 377 insertions(+), 388 deletions(-) diff --git a/lib/nexpose/scan.rb b/lib/nexpose/scan.rb index 1715548a..57aa680e 100644 --- a/lib/nexpose/scan.rb +++ b/lib/nexpose/scan.rb @@ -60,8 +60,8 @@ def scan_devices(devices) # def scan_devices_with_schedule(devices, schedules) site_id = devices.map(&:site_id).uniq.first - xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id) - elem = REXML::Element.new('Devices') + xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id) + elem = REXML::Element.new('Devices') devices.each do |device| elem.add_element('device', 'id' => "#{device.id}") end @@ -107,7 +107,7 @@ def scan_asset_with_schedule(site_id, asset, schedule) # @return [Scan] Scan launch information. # def scan_assets(site_id, assets) - xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id) + xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id) hosts = REXML::Element.new('Hosts') assets.each { |asset| _append_asset!(hosts, asset) } xml.add_element(hosts) @@ -129,7 +129,7 @@ def scan_assets(site_id, assets) # @return [Status] whether the request was successful # def scan_assets_with_schedule(site_id, assets, schedules) - xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id) + xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id) hosts = REXML::Element.new('Hosts') assets.each { |asset| _append_asset!(hosts, asset) } xml.add_element(hosts) @@ -155,7 +155,7 @@ def scan_assets_with_schedule(site_id, assets, schedules) # @return [Status] whether the request was successful # def scan_ips_with_schedule(site_id, ip_addresses, schedules) - xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id) + xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id) hosts = REXML::Element.new('Hosts') ip_addresses.each do |ip| xml.add_element('range', 'from' => ip) @@ -183,7 +183,7 @@ def scan_ips_with_schedule(site_id, ip_addresses, schedules) # @return [Scan] Scan launch information. # def scan_ips(site_id, ip_addresses) - xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id) + xml = make_xml('SiteDevicesScanRequest', 'site-id' => site_id) hosts = REXML::Element.new('Hosts') ip_addresses.each do |ip| xml.add_element('range', 'from' => ip) @@ -199,7 +199,7 @@ def scan_ips(site_id, ip_addresses) # @return [Scan] Scan launch information. # def scan_site(site_id) - xml = make_xml('SiteScanRequest', 'site-id' => site_id) + xml = make_xml('SiteScanRequest', 'site-id' => site_id) response = execute(xml) Scan.parse(response.res) if response.success end @@ -233,7 +233,7 @@ def scan_assets_with_template_and_engine(site_id, assets, scan_template, scan_en def _append_asset!(xml, asset) if asset.is_a? Nexpose::IPRange xml.add_element('range', 'from' => asset.from, 'to' => asset.to) - else # Assume HostName + else # Assume HostName host = REXML::Element.new('host') host.text = asset xml.add_element(host) @@ -368,8 +368,8 @@ def scan_statistics(scan_id) # recently completed first. # def past_scans(limit = nil) - uri = '/data/scan/global/scan-history' - rows = AJAX.row_pref_of(limit) + uri = '/data/scan/global/scan-history' + rows = AJAX.row_pref_of(limit) params = { 'sort' => 'endTime', 'dir' => 'DESC', 'startIndex' => 0 } AJAX.preserving_preference(self, 'global-completed-scans') do data = DataTable._get_json_table(self, uri, params, rows, limit) @@ -386,15 +386,15 @@ def past_scans(limit = nil) # def paused_scans(site_id = nil, limit = nil) if site_id - uri = "/data/scan/site/#{site_id}?status=active" - rows = AJAX.row_pref_of(limit) + uri = "/data/scan/site/#{site_id}?status=active" + rows = AJAX.row_pref_of(limit) params = { 'sort' => 'endTime', 'dir' => 'DESC', 'startIndex' => 0 } AJAX.preserving_preference(self, 'site-active-scans') do data = DataTable._get_json_table(self, uri, params, rows, limit).select { |scan| scan['paused'] } data.map(&ActiveScan.method(:parse_json)) end else - uri = '/data/site/scans/dyntable.xml?printDocType=0&tableID=siteScansTable&activeOnly=true' + uri = '/data/site/scans/dyntable.xml?printDocType=0&tableID=siteScansTable&activeOnly=true' data = DataTable._get_dyn_table(self, uri).select { |scan| (scan['Status'].include? 'Paused') } data.map(&ActiveScan.method(:parse_dyntable)) end @@ -409,10 +409,9 @@ def paused_scans(site_id = nil, limit = nil) # zip_file, if provided. Otherwise, returns raw ZIP binary data. # def export_scan(scan_id, zip_file = nil) - http = AJAX.https(self) - headers = { 'Cookie' => "nexposeCCSessionID=#{@session_id}", - 'Accept-Encoding' => 'identity' } - resp = http.get("/data/scan/#{scan_id}/export", headers) + http = AJAX.https(self) + headers = { 'Cookie' => "nexposeCCSessionID=#{@session_id}", 'Accept-Encoding' => 'identity' } + resp = http.get("/data/scan/#{scan_id}/export", headers) case resp when Net::HTTPSuccess @@ -502,7 +501,12 @@ class ScanData # Constructor def initialize(scan_id, site_id, engine_id, status, start_time, end_time) - @scan_id, @site_id, @engine_id, @status, @start_time, @end_time = scan_id, site_id, engine_id, status, start_time, end_time + @scan_id = scan_id + @site_id = site_id + @engine_id = engine_id + @status = status + @start_time = start_time + @end_time = end_time end def self.parse(xml) @@ -546,8 +550,16 @@ class ScanSummary < ScanData # Constructor def initialize(scan_id, site_id, engine_id, status, start_time, end_time, message, tasks, nodes, vulnerabilities) - @scan_id, @site_id, @engine_id, @status, @start_time, @end_time = scan_id, site_id, engine_id, status, start_time, end_time - @message, @tasks, @nodes, @vulnerabilities = message, tasks, nodes, vulnerabilities + @scan_id = scan_id + @site_id = site_id + @engine_id = engine_id + @status = status + @start_time = start_time + @end_time = end_time + @message = message + @tasks = tasks + @nodes = nodes + @vulnerabilities = vulnerabilities end # Parse a response from a Nexpose console into a valid ScanSummary object. @@ -594,7 +606,9 @@ class Tasks attr_reader :pending, :active, :completed def initialize(pending, active, completed) - @pending, @active, @completed = pending, active, completed + @pending = pending + @active = active + @completed = completed end # Parse REXML to Tasks object. @@ -616,7 +630,11 @@ class Nodes attr_reader :live, :dead, :filtered, :unresolved, :other def initialize(live, dead, filtered, unresolved, other) - @live, @dead, @filtered, @unresolved, @other = live, dead, filtered, unresolved, other + @live = live + @dead = dead + @filtered = filtered + @unresolved = unresolved + @other = other end # Parse REXML to Nodes object. @@ -637,19 +655,17 @@ def self.parse(rexml) # Value class for tracking vulnerability counts. # class Vulnerabilities - attr_reader :vuln_exploit, :vuln_version, :vuln_potential, - :not_vuln_exploit, :not_vuln_version, - :error, :disabled, :other - - def initialize(vuln_exploit, vuln_version, vuln_potential, - not_vuln_exploit, not_vuln_version, - error, disabled, other) - @vuln_exploit, @vuln_version, @vuln_potential, - @not_vuln_exploit, @not_vuln_version, - @error, @disabled, @other = - vuln_exploit, vuln_version, vuln_potential, - not_vuln_exploit, not_vuln_version, - error, disabled, other + attr_reader :vuln_exploit, :vuln_version, :vuln_potential, :not_vuln_exploit, :not_vuln_version, :error, :disabled, :other + + def initialize(vuln_exploit, vuln_version, vuln_potential, not_vuln_exploit, not_vuln_version, error, disabled, other) + @vuln_exploit = vuln_exploit + @vuln_version = vuln_version + @vuln_potential = vuln_potential + @not_vuln_exploit = not_vuln_exploit + @not_vuln_version = not_vuln_version + @error = error + @disabled = disabled + @other = other end # Parse REXML to Vulnerabilities object. @@ -691,11 +707,11 @@ class Status def initialize(severity = nil, count = 0) if severity @severities = {} - @count = 0 + @count = 0 add_severity(severity.to_i, count) else @severities = nil - @count = count + @count = count end end @@ -718,7 +734,8 @@ class Scan attr_reader :engine def initialize(scan_id, engine_id) - @id, @engine = scan_id, engine_id + @id = scan_id + @engine = engine_id end def self.parse(xml) @@ -781,18 +798,18 @@ def initialize(&block) # object. def self.parse_json(json) new do - @id = json['scanID'] - @site_id = json['siteID'] - @status = CompletedScan._parse_status(json['status']) - @start_time = Time.at(json['startTime'] / 1000) - @end_time = Time.at(json['endTime'] / 1000) - @duration = json['duration'] - @vulns = json['vulnerabilityCount'] - @assets = json['liveHosts'] - @risk_score = json['riskScore'] - @type = json['startedByCD'] == 'S' ? :scheduled : :manual + @id = json['scanID'] + @site_id = json['siteID'] + @status = CompletedScan._parse_status(json['status']) + @start_time = Time.at(json['startTime'] / 1000) + @end_time = Time.at(json['endTime'] / 1000) + @duration = json['duration'] + @vulns = json['vulnerabilityCount'] + @assets = json['liveHosts'] + @risk_score = json['riskScore'] + @type = json['startedByCD'] == 'S' ? :scheduled : :manual @engine_name = json['scanEngineName'] - @scan_name = json['scanName'] + @scan_name = json['scanName'] end end @@ -814,18 +831,18 @@ def self._parse_status(code) class ActiveScan < CompletedScan def self.parse_dyntable(json) new do - @id = json['Scan ID'] - @site_id = json['Site ID'] - @status = CompletedScan._parse_status(json['Status Code']) - @start_time = Time.at(json['Started'].to_i / 1000) - @end_time = Time.at(json['Progress'].to_i / 1000) - @duration = json['Elapsed'].to_i - @vulns = json['Vulnerabilities Discovered'].to_i - @assets = json['Devices Discovered'].to_i - @risk_score = json['riskScore'] - @type = json['Scan Type'] == 'Manual' ? :manual : :scheduled + @id = json['Scan ID'] + @site_id = json['Site ID'] + @status = CompletedScan._parse_status(json['Status Code']) + @start_time = Time.at(json['Started'].to_i / 1000) + @end_time = Time.at(json['Progress'].to_i / 1000) + @duration = json['Elapsed'].to_i + @vulns = json['Vulnerabilities Discovered'].to_i + @assets = json['Devices Discovered'].to_i + @risk_score = json['riskScore'] + @type = json['Scan Type'] == 'Manual' ? :manual : :scheduled @engine_name = json['Scan Engine'] - @scan_name = json['Scan Name'] + @scan_name = json['Scan Name'] end end diff --git a/lib/nexpose/scan_template.rb b/lib/nexpose/scan_template.rb index 0fd24412..5b2cbb18 100644 --- a/lib/nexpose/scan_template.rb +++ b/lib/nexpose/scan_template.rb @@ -11,7 +11,7 @@ def list_scan_templates templates['resources'].map { |t| ScanTemplateSummary.new(t) } end - alias_method :scan_templates, :list_scan_templates + alias scan_templates list_scan_templates # Delete a scan template from the console. # Cannot be used to delete a built-in template. @@ -31,7 +31,7 @@ class ScanTemplateSummary def initialize(json) @name = json['name'] - @id = json['id'] + @id = json['id'] end end @@ -110,7 +110,7 @@ def description=(description) # @return [Boolean] Whether control scanning in enabled. def control_scanning? global_controls_scan = REXML::XPath.first(@xml, 'ScanTemplate/ControlsScan/globalControlsScanEnabled') - local_controls_scan = REXML::XPath.first(@xml, 'ScanTemplate/ControlsScan/localControlsScanEnabled') + local_controls_scan = REXML::XPath.first(@xml, 'ScanTemplate/ControlsScan/localControlsScanEnabled') global_controls_scan.attributes['enabled'] == '1' || local_controls_scan.attributes['enabled'] == '1' end @@ -237,31 +237,31 @@ def enable_tcp_service_discovery=(enable) # @param [Array] ports Ports to scan for TCP service discovery def tcp_service_discovery_ports=(ports) service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/TCPPortScan') - service_ports.attributes['mode'] = "custom" - service_ports.attributes['method'] = "syn" - REXML::XPath.first(service_ports, './portList').text = ports.join(",") + service_ports.attributes['mode'] = 'custom' + service_ports.attributes['method'] = 'syn' + REXML::XPath.first(service_ports, './portList').text = ports.join(',') end # Exclude TCP ports during TCP service discovery # @param [Array] ports TCP ports to exclude from TCP service discovery def exclude_tcp_service_discovery_ports=(ports) service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/ExcludedTCPPortScan') - REXML::XPath.first(service_ports, './portList').text = ports.join(",") + REXML::XPath.first(service_ports, './portList').text = ports.join(',') end # Set custom UDP ports to scan for UDP service discovery # @param [Array] ports Ports to scan during UDP service discovery def udp_service_discovery_ports=(ports) service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/UDPPortScan') - service_ports.attributes['mode'] = "custom" - REXML::XPath.first(service_ports, './portList').text = ports.join(",") + service_ports.attributes['mode'] = 'custom' + REXML::XPath.first(service_ports, './portList').text = ports.join(',') end # Exclude UDP ports when performing UDP service discovery # @param [Array] ports UDP ports to exclude from UDP service discovery def exclude_udp_service_discovery_ports=(ports) service_ports = REXML::XPath.first(@xml, 'ScanTemplate/ServiceDiscovery/ExcludedUDPPortScan') - REXML::XPath.first(service_ports, './portList').text = ports.join(",") + REXML::XPath.first(service_ports, './portList').text = ports.join(',') end # Enable or disable UDP service discovery @@ -509,7 +509,7 @@ def self.load(nsc, id = nil) # def self.copy(nsc, id) dupe = load(nsc, id) - dupe.id = '#NewScanTemplate#' + dupe.id = '#NewScanTemplate#' dupe.name = "#{dupe.name} Copy" dupe end @@ -532,14 +532,14 @@ def aces_level=(level) return if level.nil? return unless ['full', 'default', 'none'].include? level.downcase logging = REXML::XPath.first(@xml, 'ScanTemplate/Logging') - if (logging.nil?) + if logging.nil? logging = REXML::Element.new('Logging') @xml.add_element(logging) end aces = REXML::XPath.first(logging, 'aces') - if (aces.nil?) - aces = REXML::Element.new('aces') - logging.add_element(aces) + if aces.nil? + aces = REXML::Element.new('aces') + logging.add_element(aces) end aces.attributes['level'] = level end @@ -551,13 +551,13 @@ def aces_level return 'default' if logging.nil? aces = REXML::XPath.first(logging, 'aces') return 'default' if aces.nil? - return aces.attributes['level'] + aces.attributes['level'] end # @return [Boolean] whether asset configuration scanning is enabled for # this template. def aces_enabled? - return 'full' == aces_level + aces_level == 'full' end # Enable or disable the debug logging. diff --git a/lib/nexpose/scheduled_backup.rb b/lib/nexpose/scheduled_backup.rb index af8670ac..69bb016c 100644 --- a/lib/nexpose/scheduled_backup.rb +++ b/lib/nexpose/scheduled_backup.rb @@ -22,14 +22,14 @@ class ScheduledBackup < APIObject attr_accessor :cancellation_window def initialize(start:, enabled: true, type:, interval:, platform_independent: true, description: nil, pause_local_scans: true, cancellation_window: 0) - @schedule_start = start - @enabled = enabled - @schedule_type = type - @schedule_interval = interval.to_i + @schedule_start = start + @enabled = enabled + @schedule_type = type + @schedule_interval = interval.to_i @platform_independent = platform_independent - @description = description - @pause_local_scans = pause_local_scans - @cancellation_window = cancellation_window.to_i + @description = description + @pause_local_scans = pause_local_scans + @cancellation_window = cancellation_window.to_i end def to_json @@ -72,7 +72,7 @@ def to_h end def self.load(nsc) - uri = '/api/2.1/schedule_backup/' + uri = '/api/2.1/schedule_backup/' resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) hash = JSON.parse(resp, symbolize_names: true).first Nexpose::ScheduledBackup.from_hash(hash || []) diff --git a/lib/nexpose/scheduled_maintenance.rb b/lib/nexpose/scheduled_maintenance.rb index 1641ee23..e7c35d03 100644 --- a/lib/nexpose/scheduled_maintenance.rb +++ b/lib/nexpose/scheduled_maintenance.rb @@ -24,14 +24,14 @@ class ScheduledMaintenance < APIObject attr_accessor :cancellation_window def initialize(start:, enabled: true, type:, interval:, reindex: false, compress: true, cleanup: true, pause_local_scans: true, cancellation_window: 0) - @schedule_start = start - @enabled = enabled - @schedule_type = type - @schedule_interval = interval.to_i - @reindex = reindex - @compress = compress - @cleanup = cleanup - @pause_local_scans = pause_local_scans + @schedule_start = start + @enabled = enabled + @schedule_type = type + @schedule_interval = interval.to_i + @reindex = reindex + @compress = compress + @cleanup = cleanup + @pause_local_scans = pause_local_scans @cancellation_window = cancellation_window.to_i end @@ -77,7 +77,7 @@ def to_h end def self.load(nsc) - uri = '/api/2.1/schedule_maintenance/' + uri = '/api/2.1/schedule_maintenance/' resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) hash = JSON.parse(resp, symbolize_names: true).first Nexpose::ScheduledMaintenance.from_hash(hash || []) diff --git a/lib/nexpose/shared_credential.rb b/lib/nexpose/shared_credential.rb index aa40fe3f..801167fa 100644 --- a/lib/nexpose/shared_credential.rb +++ b/lib/nexpose/shared_credential.rb @@ -4,21 +4,21 @@ class Connection def list_shared_credentials creds = DataTable._get_json_table(self, - '/data/credential/shared/listing', - { 'sort' => -1, - 'table-id' => 'credential-listing' }) + '/data/credential/shared/listing', + { 'sort' => -1, + 'table-id' => 'credential-listing' }) creds.map { |c| SharedCredentialSummary.from_json(c) } end - alias_method :list_shared_creds, :list_shared_credentials - alias_method :shared_credentials, :list_shared_credentials - alias_method :shared_creds, :list_shared_credentials + alias list_shared_creds list_shared_credentials + alias shared_credentials list_shared_credentials + alias shared_creds list_shared_credentials def delete_shared_credential(id) AJAX.post(self, "/data/credential/shared/delete?credid=#{id}") end - alias_method :delete_shared_cred, :delete_shared_credential + alias delete_shared_cred delete_shared_credential end class SharedCredentialSummary < Credential @@ -29,18 +29,18 @@ class SharedCredentialSummary < Credential attr_accessor :name # The credential service/type. See Nexpose::Credential::Service. attr_accessor :service - alias :type :service - alias :type= :service= + alias type service + alias type= service= # Domain or realm. attr_accessor :domain # User name. attr_accessor :username - alias :user_name :username - alias :user_name= :username= + alias user_name username + alias user_name= username= # User name to use when elevating permissions (e.g., sudo). attr_accessor :privilege_username - alias :permission_elevation_user :privilege_username - alias :permission_elevation_user= :privilege_username= + alias permission_elevation_user privilege_username + alias permission_elevation_user= privilege_username= # Boolean to indicate whether this credential applies to all sites. attr_accessor :all_sites # When this credential was last modified. @@ -48,14 +48,14 @@ class SharedCredentialSummary < Credential def self.from_json(json) cred = new - cred.id = json['credentialID']['ID'] - cred.name = json['name'] - cred.type = json['service'] - cred.domain = json['domain'] - cred.username = json['username'] + cred.id = json['credentialID']['ID'] + cred.name = json['name'] + cred.type = json['service'] + cred.domain = json['domain'] + cred.username = json['username'] cred.privilege_username = json['privilegeElevationUsername'] - cred.all_sites = json['scope'] == 'ALL_SITES_ENABLED_DEFAULT' - cred.last_modified = Time.at(json['lastModified']['time'] / 1000) + cred.all_sites = json['scope'] == 'ALL_SITES_ENABLED_DEFAULT' + cred.last_modified = Time.at(json['lastModified']['time'] / 1000) cred end @@ -83,12 +83,12 @@ class SharedCredential < SharedCredentialSummary attr_accessor :pem_key # Password to use when elevating permissions (e.g., sudo). attr_accessor :privilege_password - alias :permission_elevation_password :privilege_password - alias :permission_elevation_password= :privilege_password= + alias permission_elevation_password privilege_password + alias permission_elevation_password= privilege_password= # Permission elevation type. See Nexpose::Credential::ElevationType. attr_accessor :privilege_type - alias :permission_elevation_type :privilege_type - alias :permission_elevation_type= :privilege_type= + alias permission_elevation_type privilege_type + alias permission_elevation_type= privilege_type= # Privacty password of SNMP v3 credential attr_accessor :privacy_password # Authentication type of SNMP v3 credential @@ -130,17 +130,14 @@ def save(nsc) def as_xml xml = REXML::Element.new('Credential') xml.add_attribute('id', @id) - - name = xml.add_element('Name').add_text(@name) - - desc = xml.add_element('Description').add_text(@description) + xml.add_element('Name').add_text(@name) + xml.add_element('Description').add_text(@description) services = xml.add_element('Services') - service = services.add_element('Service').add_attribute('type', @service) + services.add_element('Service').add_attribute('type', @service) (account = xml.add_element('Account')).add_attribute('type', 'nexpose') account.add_element('Field', { 'name' => 'database' }).add_text(@database) - account.add_element('Field', { 'name' => 'domain' }).add_text(@domain) account.add_element('Field', { 'name' => 'username' }).add_text(@username) account.add_element('Field', { 'name' => 'ntlmhash' }).add_text(@ntlm_hash) if @ntlm_hash @@ -188,10 +185,10 @@ def test(nsc, target, engine_id = nil, siteid = -1) unless engine_id engine_id = nsc.engines.detect { |e| e.name == 'Local scan engine' }.id end - @port = Credential::DEFAULT_PORTS[@service] if @port.nil? + @port = Credential::DEFAULT_PORTS[@service] if @port.nil? parameters = _to_param(target, engine_id, @port, siteid) - xml = AJAX.form_post(nsc, '/data/credential/shared/test', parameters) - result = REXML::XPath.first(REXML::Document.new(xml), 'TestAdminCredentialsResult') + xml = AJAX.form_post(nsc, '/data/credential/shared/test', parameters) + result = REXML::XPath.first(REXML::Document.new(xml), 'TestAdminCredentialsResult') result.attributes['success'].to_i == 1 end diff --git a/lib/nexpose/shared_secret.rb b/lib/nexpose/shared_secret.rb index 7a56b407..54feb0c8 100644 --- a/lib/nexpose/shared_secret.rb +++ b/lib/nexpose/shared_secret.rb @@ -5,14 +5,14 @@ class SharedSecret < APIObject attr_reader :ttl def initialize(console, time_to_live) - uri = "/data/admin/global/shared-secret?time-to-live=#{time_to_live}" + uri = "/data/admin/global/shared-secret?time-to-live=#{time_to_live}" json = JSON.parse(AJAX.put(console, uri)) self.from_json(json) end def from_json(json) @key_string = json['keyString'] - @ttl = json['timeToLiveInSeconds'] + @ttl = json['timeToLiveInSeconds'] end def delete(console) @@ -22,10 +22,10 @@ def delete(console) def ==(other) return false unless self.class == other.class - return false unless key_string.upcase == other.key_string.upcase - + return false unless key_string.casecmp(other.key_string) true end - alias_method :eql?, :== + alias eql? == end + end diff --git a/lib/nexpose/silo.rb b/lib/nexpose/silo.rb index bc54d2ed..13c8f2f1 100644 --- a/lib/nexpose/silo.rb +++ b/lib/nexpose/silo.rb @@ -18,14 +18,14 @@ def list_silos arr end - alias_method :silos, :list_silos + alias silos list_silos # Delete the specified silo # # @return Whether or not the delete request succeeded. # def delete_silo(silo_id) - r = execute(make_xml('SiloDeleteRequest', {'silo-id' => silo_id}), '1.2') + r = execute(make_xml('SiloDeleteRequest', { 'silo-id' => silo_id }), '1.2') r.success end end @@ -39,13 +39,13 @@ class Silo attr_accessor :max_users attr_accessor :max_hosted_assets - #Optional fields + # Optional fields attr_accessor :description attr_accessor :merchant attr_accessor :organization def initialize(&block) - instance_eval &block if block_given? + instance_eval(&block) if block_given? end # Copy an existing configuration from a Nexpose instance. @@ -56,8 +56,8 @@ def initialize(&block) # @return [Silo] Silo configuration loaded from a Nexpose console. # def self.copy(connection, id) - silo = load(connection, id) - silo.id = nil + silo = load(connection, id) + silo.id = nil silo.name = nil silo end @@ -69,7 +69,7 @@ def self.copy(connection, id) # @return [Silo] Silo configuration loaded from a Nexpose console. # def self.load(connection, id) - r = connection.execute(connection.make_xml('SiloConfigRequest', {'silo-id' => id}), '1.2') + r = connection.execute(connection.make_xml('SiloConfigRequest', { 'silo-id' => id }), '1.2') if r.success r.res.elements.each('SiloConfigResponse/SiloConfig') do |config| @@ -80,12 +80,10 @@ def self.load(connection, id) end def save(connection) - begin - update(connection) - rescue APIError => error - raise error unless (error.message =~ /A silo .* does not exist./) - create(connection) - end + update(connection) + rescue APIError => error + raise error unless error.message =~ /A silo .* does not exist./ + create(connection) end # Updates this silo on a Nexpose console. @@ -118,7 +116,8 @@ def delete(connection) def as_xml xml = REXML::Element.new('SiloConfig') - xml.add_attributes({'description' => @description, 'name' => @name, 'id' => @id, 'silo-profile-id' => @profile_id, 'max-assets' => @max_assets, 'max-users' => @max_users, 'max-hosted-assets' => @max_hosted_assets}) + xml.add_attributes({ 'description' => @description, 'name' => @name, 'id' => @id, 'silo-profile-id' => @profile_id, + 'max-assets' => @max_assets, 'max-users' => @max_users, 'max-hosted-assets' => @max_hosted_assets }) xml.add(@merchant.as_xml) if @merchant xml.add(@organization.as_xml) if @organization xml @@ -130,13 +129,13 @@ def to_xml def self.parse(xml) new do |silo| - silo.id = xml.attributes['id'] - silo.profile_id = xml.attributes['silo-profile-id'] - silo.name = xml.attributes['name'] - silo.max_assets = xml.attributes['max-assets'].to_i - silo.max_users = xml.attributes['max-users'].to_i + silo.id = xml.attributes['id'] + silo.profile_id = xml.attributes['silo-profile-id'] + silo.name = xml.attributes['name'] + silo.max_assets = xml.attributes['max-assets'].to_i + silo.max_users = xml.attributes['max-users'].to_i silo.max_hosted_assets = xml.attributes['max-hosted-assets'].to_i - silo.description = xml.attributes['description'] + silo.description = xml.attributes['description'] xml.elements.each('Merchant') do |merchant| silo.merchant = Merchant.parse(merchant) @@ -156,25 +155,24 @@ class Address attr_accessor :zip attr_accessor :country - def initialize(&block) - instance_eval &block if block_given? + instance_eval(&block) if block_given? end def self.parse(xml) new do |address| - address.line1 = xml.attributes['line1'] - address.line2 = xml.attributes['line2'] - address.city = xml.attributes['city'] - address.state = xml.attributes['state'] - address.zip = xml.attributes['zip'] + address.line1 = xml.attributes['line1'] + address.line2 = xml.attributes['line2'] + address.city = xml.attributes['city'] + address.state = xml.attributes['state'] + address.zip = xml.attributes['zip'] address.country = xml.attributes['country'] end end def as_xml xml = REXML::Element.new('Address') - xml.add_attributes({'city' => @city, 'country' => @country, 'line1' => @line1, 'line2' => @line2, 'state' => @state, 'zip' => @zip}) + xml.add_attributes({ 'city' => @city, 'country' => @country, 'line1' => @line1, 'line2' => @line2, 'state' => @state, 'zip' => @zip }) xml end end @@ -190,28 +188,29 @@ class Organization attr_accessor :url def initialize(&block) - instance_eval &block if block_given? + instance_eval(&block) if block_given? end def as_xml xml = REXML::Element.new('Organization') - xml.add_attributes({'company' => @company, 'email-address' => @email, 'first-name' => @first_name, 'last-name' => @last_name, 'phone-number' => @phone, 'title' => @title, 'url' => @url}) + xml.add_attributes({ 'company' => @company, 'email-address' => @email, 'first-name' => @first_name, + 'last-name' => @last_name, 'phone-number' => @phone, 'title' => @title, 'url' => @url }) xml.add(@address.as_xml) xml end def self.parse(xml) new do |organization| - organization.company = xml.attributes['company'] + organization.company = xml.attributes['company'] organization.first_name = xml.attributes['first-name'] - organization.last_name = xml.attributes['last-name'] - organization.phone = xml.attributes['phone-number'] + organization.last_name = xml.attributes['last-name'] + organization.phone = xml.attributes['phone-number'] xml.elements.each('Address') do |address| organization.address = Address.parse(address) end organization.email = xml.attributes['email'] organization.title = xml.attributes['title'] - organization.url = xml.attributes['url'] + organization.url = xml.attributes['url'] end end end @@ -233,32 +232,32 @@ class Merchant < Organization attr_accessor :qsa def initialize(&block) - instance_eval &block if block_given? - @dbas = Array(@dbas) + instance_eval(&block) if block_given? + @dbas = Array(@dbas) @industries = Array(@industries) - @qsa = Array(@qsa) + @qsa = Array(@qsa) end def self.parse(xml) new do |merchant| merchant.acquirer_relationship = xml.attributes['acquirer-relationship'].to_s.chomp.eql?('true') - merchant.agent_relationship = xml.attributes['agent-relationship'].to_s.chomp.eql?('true') - merchant.ecommerce = xml.attributes['ecommerce'].to_s.chomp.eql?('true') - merchant.grocery = xml.attributes['grocery'].to_s.chomp.eql?('true') - merchant.mail_order = xml.attributes['mail-order'].to_s.chomp.eql?('true') - merchant.payment_application = xml.attributes['payment-application'] - merchant.payment_version = xml.attributes['payment-version'] - merchant.petroleum = xml.attributes['petroleum'].to_s.chomp.eql?('true') - merchant.retail = xml.attributes['retail'].to_s.chomp.eql?('true') - merchant.telecommunication = xml.attributes['telecommunication'].to_s.chomp.eql?('true') - merchant.travel = xml.attributes['travel'].to_s.chomp.eql?('true') - merchant.company = xml.attributes['company'] - merchant.first_name = xml.attributes['first-name'] - merchant.last_name = xml.attributes['last-name'] - merchant.phone = xml.attributes['phone-number'] - merchant.email = xml.attributes['email'] - merchant.title = xml.attributes['title'] - merchant.url = xml.attributes['url'] + merchant.agent_relationship = xml.attributes['agent-relationship'].to_s.chomp.eql?('true') + merchant.ecommerce = xml.attributes['ecommerce'].to_s.chomp.eql?('true') + merchant.grocery = xml.attributes['grocery'].to_s.chomp.eql?('true') + merchant.mail_order = xml.attributes['mail-order'].to_s.chomp.eql?('true') + merchant.payment_application = xml.attributes['payment-application'] + merchant.payment_version = xml.attributes['payment-version'] + merchant.petroleum = xml.attributes['petroleum'].to_s.chomp.eql?('true') + merchant.retail = xml.attributes['retail'].to_s.chomp.eql?('true') + merchant.telecommunication = xml.attributes['telecommunication'].to_s.chomp.eql?('true') + merchant.travel = xml.attributes['travel'].to_s.chomp.eql?('true') + merchant.company = xml.attributes['company'] + merchant.first_name = xml.attributes['first-name'] + merchant.last_name = xml.attributes['last-name'] + merchant.phone = xml.attributes['phone-number'] + merchant.email = xml.attributes['email'] + merchant.title = xml.attributes['title'] + merchant.url = xml.attributes['url'] xml.elements.each('Address') do |address| merchant.address = Address.parse(address) @@ -284,20 +283,22 @@ def self.parse(xml) def as_xml xml = super xml.name = 'Merchant' - xml.add_attributes({'acquirer-relationship' => @acquirer_relationship, 'agent-relationship' => @agent_relationship, 'ecommerce' => @ecommerce, 'grocery' => @grocery, 'mail-order' => @mail_order}) - xml.add_attributes({'payment-application' => @payment_application, 'payment-version' => @payment_version, 'petroleum' => @petroleum, 'retail' => @retail, 'telecommunication' => @telecommunication, 'travel' => @travel}) + xml.add_attributes({ 'acquirer-relationship' => @acquirer_relationship, 'agent-relationship' => @agent_relationship, + 'ecommerce' => @ecommerce, 'grocery' => @grocery, 'mail-order' => @mail_order }) + xml.add_attributes({ 'payment-application' => @payment_application, 'payment-version' => @payment_version, + 'petroleum' => @petroleum, 'retail' => @retail, 'telecommunication' => @telecommunication, 'travel' => @travel }) unless dbas.empty? dbas = REXML::Element.new('DBAs') @dbas.each do |dba| - dbas.add_element('DBA', {'name' => dba}) + dbas.add_element('DBA', { 'name' => dba }) end end unless @industries.empty? industries = REXML::Element.new('OtherIndustries') @industries.each do |industry| - industries.add_element('Industry', {'name' => industry}) + industries.add_element('Industry', { 'name' => industry }) end end @@ -331,23 +332,24 @@ class SiloSummary attr_reader :max_users def initialize(&block) - instance_eval &block if block_given? + instance_eval(&block) if block_given? end def self.parse(xml) new do - @id = xml.attributes['id'] - @name = xml.attributes['name'] + @id = xml.attributes['id'] + @name = xml.attributes['name'] @description = xml.attributes['description'] - @profile_id = xml.attributes['silo-profile-id'] + @profile_id = xml.attributes['silo-profile-id'] xml.elements.each('LicenseSummary') do |license| - @assets = license.attributes['assets'] - @max_assets = license.attributes['max-assets'] + @assets = license.attributes['assets'] + @max_assets = license.attributes['max-assets'] @max_hosted_assets = license.attributes['max-hosted-assets'] - @users = license.attributes['users'] - @max_users = license.attributes['max-users'] + @users = license.attributes['users'] + @max_users = license.attributes['max-users'] end end end end + end diff --git a/lib/nexpose/silo_profile.rb b/lib/nexpose/silo_profile.rb index 9783ee6c..d5530f96 100644 --- a/lib/nexpose/silo_profile.rb +++ b/lib/nexpose/silo_profile.rb @@ -18,14 +18,14 @@ def list_silo_profiles arr end - alias_method :silo_profiles, :list_silo_profiles + alias silo_profiles list_silo_profiles # Delete the specified silo profile # # @return Whether or not the delete request succeeded. # def delete_silo_profile(silo_profile_id) - r = execute(make_xml('SiloProfileDeleteRequest', {'silo-profile-id' => silo_profile_id}), '1.2') + r = execute(make_xml('SiloProfileDeleteRequest', { 'silo-profile-id' => silo_profile_id }), '1.2') r.success end end @@ -46,24 +46,24 @@ class SiloProfile attr_accessor :restricted_report_sections def initialize(&block) - instance_eval &block if block_given? - @global_report_templates = Array(@global_report_templates) - @global_scan_engines = Array(@global_scan_engines) - @global_scan_templates = Array(@global_scan_templates) - @licensed_modules = Array(@licensed_modules) - @restricted_report_formats = Array(@restricted_report_formats) + instance_eval(&block) if block_given? + @global_report_templates = Array(@global_report_templates) + @global_scan_engines = Array(@global_scan_engines) + @global_scan_templates = Array(@global_scan_templates) + @licensed_modules = Array(@licensed_modules) + @restricted_report_formats = Array(@restricted_report_formats) @restricted_report_sections = Array(@restricted_report_sections) end def self.copy(connection, id) - profile = load(connection, id) - profile.id = nil + profile = load(connection, id) + profile.id = nil profile.name = nil profile end def self.load(connection, id) - r = connection.execute(connection.make_xml('SiloProfileConfigRequest', {'silo-profile-id' => id}), '1.2') + r = connection.execute(connection.make_xml('SiloProfileConfigRequest', { 'silo-profile-id' => id }), '1.2') if r.success r.res.elements.each('SiloProfileConfigResponse/SiloProfileConfig') do |config| @@ -75,13 +75,13 @@ def self.load(connection, id) def self.parse(xml) new do |profile| - profile.id = xml.attributes['id'] - profile.name = xml.attributes['name'] - profile.description = xml.attributes['description'] - profile.all_licensed_modules = xml.attributes['all-licensed-modules'].to_s.chomp.eql?('true') - profile.all_global_engines = xml.attributes['all-global-engines'].to_s.chomp.eql?('true') + profile.id = xml.attributes['id'] + profile.name = xml.attributes['name'] + profile.description = xml.attributes['description'] + profile.all_licensed_modules = xml.attributes['all-licensed-modules'].to_s.chomp.eql?('true') + profile.all_global_engines = xml.attributes['all-global-engines'].to_s.chomp.eql?('true') profile.all_global_report_templates = xml.attributes['all-global-report-templates'].to_s.chomp.eql?('true') - profile.all_global_scan_templates = xml.attributes['all-global-scan-templates'].to_s.chomp.eql?('true') + profile.all_global_scan_templates = xml.attributes['all-global-scan-templates'].to_s.chomp.eql?('true') profile.global_report_templates = [] xml.elements.each('GlobalReportTemplates/GlobalReportTemplate') { |template| profile.global_report_templates << template.attributes['name'] } @@ -104,12 +104,10 @@ def self.parse(xml) end def save(connection) - begin - update(connection) - rescue APIError => error - raise error unless (error.message =~ /silo profile(\S*|.*?)does not exist/i) - create(connection) - end + update(connection) + rescue APIError => error + raise error unless error.message =~ /silo profile(\S*|.*?)does not exist/i + create(connection) end # Updates an existing silo profile on a Nexpose console. @@ -142,53 +140,53 @@ def delete(connection) def as_xml xml = REXML::Element.new('SiloProfileConfig') - xml.add_attributes({'id' => @id, - 'name' => @name, - 'description' => @description, - 'all-licensed-modules' => @all_licensed_modules, - 'all-global-engines' => @all_global_engines, - 'all-global-report-templates' => @all_global_report_templates, - 'all-global-scan-templates' => @all_global_scan_templates}) + xml.add_attributes({ 'id' => @id, + 'name' => @name, + 'description' => @description, + 'all-licensed-modules' => @all_licensed_modules, + 'all-global-engines' => @all_global_engines, + 'all-global-report-templates' => @all_global_report_templates, + 'all-global-scan-templates' => @all_global_scan_templates }) unless @global_report_templates.empty? templates = xml.add_element('GlobalReportTemplates') @global_report_templates.each do |template| - templates.add_element('GlobalReportTemplate', {'name' => template}) + templates.add_element('GlobalReportTemplate', { 'name' => template }) end end unless @global_scan_engines.empty? engines = xml.add_element('GlobalScanEngines') @global_scan_engines.each do |engine| - engines.add_element('GlobalScanEngine', {'name' => engine}) + engines.add_element('GlobalScanEngine', { 'name' => engine }) end end unless @global_scan_templates.empty? templates = xml.add_element('GlobalScanTemplates') @global_scan_templates.each do |template| - templates.add_element('GlobalScanTemplate', {'name' => template}) + templates.add_element('GlobalScanTemplate', { 'name' => template }) end end unless @licensed_modules.empty? licensed_modules = xml.add_element('LicensedModules') @licensed_modules.each do |licensed_module| - licensed_modules.add_element('LicensedModule', {'name' => licensed_module}) + licensed_modules.add_element('LicensedModule', { 'name' => licensed_module }) end end unless @restricted_report_formats.empty? formats = xml.add_element('RestrictedReportFormats') @restricted_report_formats.each do |format| - formats.add_element('RestrictedReportFormat', {'name' => format}) + formats.add_element('RestrictedReportFormat', { 'name' => format }) end end unless @restricted_report_sections.empty? sections = xml.add_element('RestrictedReportSections') @restricted_report_sections.each do |section| - sections.add_element('RestrictedReportSection', {'name' => section}) + sections.add_element('RestrictedReportSection', { 'name' => section }) end end @@ -214,26 +212,25 @@ class SiloProfileSummary attr_reader :all_global_report_templates attr_reader :all_global_scan_templates - def initialize(&block) - instance_eval &block if block_given? + instance_eval(&block) if block_given? end def self.parse(xml) new do - @id = xml.attributes['id'] - @name = xml.attributes['name'] - @description = xml.attributes['description'] - @global_report_template_count = xml.attributes['global-report-template-count'] - @global_scan_engine_count = xml.attributes['global-scan-engine-count'] - @global_scan_template_count = xml.attributes['global-scan-template-count'] - @licensed_module_count = xml.attributes['licensed-module-count'] + @id = xml.attributes['id'] + @name = xml.attributes['name'] + @description = xml.attributes['description'] + @global_report_template_count = xml.attributes['global-report-template-count'] + @global_scan_engine_count = xml.attributes['global-scan-engine-count'] + @global_scan_template_count = xml.attributes['global-scan-template-count'] + @licensed_module_count = xml.attributes['licensed-module-count'] @restricted_report_section_count = xml.attributes['restricted-report-section-count'] - @all_licensed_modules = xml.attributes['all-licensed-modules'] - @all_global_engines = xml.attributes['all-global-engines'] - @all_global_report_templates = xml.attributes['all-global-report-templates'] - @all_global_scan_templates = xml.attributes['all-global-scan-templates'] + @all_licensed_modules = xml.attributes['all-licensed-modules'] + @all_global_engines = xml.attributes['all-global-engines'] + @all_global_report_templates = xml.attributes['all-global-report-templates'] + @all_global_scan_templates = xml.attributes['all-global-scan-templates'] end end end -end \ No newline at end of file +end diff --git a/lib/nexpose/site.rb b/lib/nexpose/site.rb index 8500718b..2bba0d1d 100644 --- a/lib/nexpose/site.rb +++ b/lib/nexpose/site.rb @@ -22,7 +22,7 @@ def list_sites arr end - alias_method :sites, :list_sites + alias sites list_sites # Delete the specified site and all associated scan data. # @@ -69,7 +69,7 @@ def last_scan(site_id) # def completed_scans(site_id) table = { 'table-id' => 'site-completed-scans' } - data = DataTable._get_json_table(self, "/data/scan/site/#{site_id}", table) + data = DataTable._get_json_table(self, "/data/scan/site/#{site_id}", table) data.map(&CompletedScan.method(:parse_json)) end end @@ -158,21 +158,21 @@ class Site < APIObject # @param [String] name Unique name of the site. # @param [String] scan_template_id ID of the scan template to use. def initialize(name = nil, scan_template_id = 'full-audit-without-web-spider') - @name = name - @scan_template_id = scan_template_id - @id = -1 - @risk_factor = 1.0 - @config_version = 3 - @schedules = [] - @blackouts = [] + @name = name + @scan_template_id = scan_template_id + @id = -1 + @risk_factor = 1.0 + @config_version = 3 + @schedules = [] + @blackouts = [] @included_scan_targets = { addresses: [], asset_groups: [] } @excluded_scan_targets = { addresses: [], asset_groups: [] } - @site_credentials = [] - @shared_credentials = [] - @web_credentials = [] - @alerts = [] - @users = [] - @tags = [] + @site_credentials = [] + @shared_credentials = [] + @web_credentials = [] + @alerts = [] + @users = [] + @tags = [] end # Returns the array of included scan target addresses. @@ -231,23 +231,20 @@ def excluded_asset_groups=(new_asset_groups) def is_dynamic? !@discovery_config.nil? end + alias dynamic? is_dynamic? # Adds assets to this site by IP address range. # # @param [String] from Beginning IP address of a range. # @param [String] to Ending IP address of a range. def include_ip_range(from, to) - begin - from_ip = IPAddr.new(from) - to_ip = IPAddr.new(to) - (from_ip..to_ip) - if (from_ip..to_ip).to_a.size == 0 - raise 'Invalid IP range specified' - end - @included_scan_targets[:addresses] << IPRange.new(from, to) - rescue ArgumentError => e - raise "#{e.message} in given IP range" - end + from_ip = IPAddr.new(from) + to_ip = IPAddr.new(to) + (from_ip..to_ip) + raise 'Invalid IP range specified' if (from_ip..to_ip).to_a.size.zero? + @included_scan_targets[:addresses] << IPRange.new(from, to) + rescue ArgumentError => e + raise "#{e.message} in given IP range" end # Remove assets to this site by IP address range. @@ -255,17 +252,13 @@ def include_ip_range(from, to) # @param [String] from Beginning IP address of a range. # @param [String] to Ending IP address of a range. def remove_included_ip_range(from, to) - begin - from_ip = IPAddr.new(from) - to_ip = IPAddr.new(to) - (from_ip..to_ip) - if (from_ip..to_ip).to_a.size == 0 - raise 'Invalid IP range specified' - end - @included_scan_targets[:addresses].reject! { |t| t.eql? IPRange.new(from, to) } - rescue ArgumentError => e - raise "#{e.message} in given IP range" - end + from_ip = IPAddr.new(from) + to_ip = IPAddr.new(to) + (from_ip..to_ip) + raise 'Invalid IP range specified' if (from_ip..to_ip).to_a.size.zero? + @included_scan_targets[:addresses].reject! { |t| t.eql? IPRange.new(from, to) } + rescue ArgumentError => e + raise "#{e.message} in given IP range" end # Adds an asset to this site included scan targets, resolving whether an IP or hostname is @@ -291,17 +284,13 @@ def remove_included_asset(asset) # @param [String] from Beginning IP address of a range. # @param [String] to Ending IP address of a range. def exclude_ip_range(from, to) - begin - from_ip = IPAddr.new(from) - to_ip = IPAddr.new(to) - (from_ip..to_ip) - if (from_ip..to_ip).to_a.size == 0 - raise 'Invalid IP range specified' - end - @excluded_scan_targets[:addresses] << IPRange.new(from, to) - rescue ArgumentError => e - raise "#{e.message} in given IP range" - end + from_ip = IPAddr.new(from) + to_ip = IPAddr.new(to) + (from_ip..to_ip) + raise 'Invalid IP range specified' if (from_ip..to_ip).to_a.size.zero? + @excluded_scan_targets[:addresses] << IPRange.new(from, to) + rescue ArgumentError => e + raise "#{e.message} in given IP range" end # Remove assets from this site excluded scan targets by IP address range. @@ -309,17 +298,13 @@ def exclude_ip_range(from, to) # @param [String] from Beginning IP address of a range. # @param [String] to Ending IP address of a range. def remove_excluded_ip_range(from, to) - begin - from_ip = IPAddr.new(from) - to_ip = IPAddr.new(to) - (from_ip..to_ip) - if (from_ip..to_ip).to_a.size == 0 - raise 'Invalid IP range specified' - end - @excluded_scan_targets[:addresses].reject! { |t| t.eql? IPRange.new(from, to) } - rescue ArgumentError => e - raise "#{e.message} in given IP range" - end + from_ip = IPAddr.new(from) + to_ip = IPAddr.new(to) + (from_ip..to_ip) + raise 'Invalid IP range specified' if (from_ip..to_ip).to_a.size.zero? + @excluded_scan_targets[:addresses].reject! { |t| t.eql? IPRange.new(from, to) } + rescue ArgumentError => e + raise "#{e.message} in given IP range" end # Adds an asset to this site excluded scan targets, resolving whether an IP or hostname is @@ -391,7 +376,7 @@ def add_user(user_id) raise 'Invalid user id. A user id must be a positive number and refer to an existing system user.' end - @users << { id: user_id} + @users << { id: user_id } end def remove_user(user_id) @@ -427,36 +412,29 @@ def to_json end def to_h - included_scan_targets = { - addresses: @included_scan_targets[:addresses].compact, - asset_groups: @included_scan_targets[:asset_groups].compact - } - excluded_scan_targets = { - addresses: @excluded_scan_targets[:addresses].compact, - asset_groups: @excluded_scan_targets[:asset_groups].compact - } - - hash = { - id: @id, - name: @name, - description: @description, - auto_engine_selection_enabled: @auto_engine_selection_enabled, - included_scan_targets: included_scan_targets, - excluded_scan_targets: excluded_scan_targets, - engine_id: @engine_id, - scan_template_id: @scan_template_id, - risk_factor: @risk_factor, - schedules: (@schedules || []).map {|schedule| schedule.to_h}, - shared_credentials: (@shared_credentials || []).map {|cred| cred.to_h}, - site_credentials: (@site_credentials || []).map {|cred| cred.to_h}, - web_credentials: (@web_credentials || []).map {|webCred| webCred.to_h}, - discovery_config: @discovery_config.to_h, - search_criteria: @search_criteria.to_h, - tags: (@tags || []).map{|tag| tag.to_h}, - alerts: (@alerts || []).map {|alert| alert.to_h }, - organization: @organization.to_h, - users: users - } + included_scan_targets = { addresses: @included_scan_targets[:addresses].compact, + asset_groups: @included_scan_targets[:asset_groups].compact } + excluded_scan_targets = { addresses: @excluded_scan_targets[:addresses].compact, + asset_groups: @excluded_scan_targets[:asset_groups].compact } + hash = { id: @id, + name: @name, + description: @description, + auto_engine_selection_enabled: @auto_engine_selection_enabled, + included_scan_targets: included_scan_targets, + excluded_scan_targets: excluded_scan_targets, + engine_id: @engine_id, + scan_template_id: @scan_template_id, + risk_factor: @risk_factor, + schedules: (@schedules || []).map(&:to_h), + shared_credentials: (@shared_credentials || []).map(&:to_h), + site_credentials: (@site_credentials || []).map(&:to_h), + web_credentials: (@web_credentials || []).map(&:to_h), + discovery_config: @discovery_config.to_h, + search_criteria: @search_criteria.to_h, + tags: (@tags || []).map(&:to_h), + alerts: (@alerts || []).map(&:to_h), + organization: @organization.to_h, + users: users } # @TODO: Revisit this for 2.0.0 update # Only pass in blackouts if they were actually specified (for backwards compatibility) hash[:blackouts] = @blackouts.map(&:to_h) if @blackouts && @blackouts.any? @@ -472,7 +450,7 @@ def to_h # @return [Site] The requested site, if found. # def self.load(nsc, id) - uri = "/api/2.1/site_configurations/#{id}" + uri = "/api/2.1/site_configurations/#{id}" resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) hash = JSON.parse(resp, symbolize_names: true) site = self.json_initializer(hash).deserialize(hash) @@ -486,19 +464,19 @@ def self.load(nsc, id) site.excluded_scan_targets[:addresses] = [] excluded_addresses.each { |asset| site.exclude_asset(asset) } - site.organization = Organization.create(site.organization) - site.schedules = (hash[:schedules] || []).map {|schedule| Nexpose::Schedule.from_hash(schedule) } - site.blackouts = (hash[:blackouts] || []).map {|blackout| Nexpose::Blackout.from_hash(blackout) } - site.site_credentials = hash[:site_credentials].map {|cred| Nexpose::SiteCredentials.new.object_from_hash(nsc,cred)} - site.shared_credentials = hash[:shared_credentials].map {|cred| Nexpose::SiteCredentials.new.object_from_hash(nsc,cred)} - site.discovery_config = Nexpose::DiscoveryConnection.new.object_from_hash(nsc, hash[:discovery_config]) unless hash[:discovery_config].nil? - site.search_criteria = Nexpose::DiscoveryConnection::Criteria.parseHash(hash[:search_criteria]) unless hash[:search_criteria].nil? - site.alerts = Alert.load_alerts(hash[:alerts]) - site.tags = Tag.load_tags(hash[:tags]) - site.web_credentials = hash[:web_credentials].map {|webCred| ( - webCred[:service] == Nexpose::WebCredentials::WebAppAuthType::HTTP_HEADER ? - Nexpose::WebCredentials::Headers.new(webCred[:name], webCred[:baseURL], webCred[:soft403Pattern], webCred[:id]).object_from_hash(nsc,webCred) : - Nexpose::WebCredentials::HTMLForms.new(webCred[:name], webCred[:baseURL], webCred[:loginURL], webCred[:soft403Pattern], webCred[:id]).object_from_hash(nsc,webCred))} + site.organization = Organization.create(site.organization) + site.schedules = (hash[:schedules] || []).map { |schedule| Nexpose::Schedule.from_hash(schedule) } + site.blackouts = (hash[:blackouts] || []).map { |blackout| Nexpose::Blackout.from_hash(blackout) } + site.site_credentials = hash[:site_credentials].map { |cred| Nexpose::SiteCredentials.new.object_from_hash(nsc, cred) } + site.shared_credentials = hash[:shared_credentials].map { |cred| Nexpose::SiteCredentials.new.object_from_hash(nsc, cred) } + site.discovery_config = Nexpose::DiscoveryConnection.new.object_from_hash(nsc, hash[:discovery_config]) unless hash[:discovery_config].nil? + site.search_criteria = Nexpose::DiscoveryConnection::Criteria.parseHash(hash[:search_criteria]) unless hash[:search_criteria].nil? + site.alerts = Alert.load_alerts(hash[:alerts]) + site.tags = Tag.load_tags(hash[:tags]) + site.web_credentials = hash[:web_credentials].map { |web_cred| ( + web_cred[:service] == Nexpose::WebCredentials::WebAppAuthType::HTTP_HEADER ? + Nexpose::WebCredentials::Headers.new(web_cred[:name], web_cred[:baseURL], web_cred[:soft403Pattern], web_cred[:id]).object_from_hash(nsc, web_cred) : + Nexpose::WebCredentials::HTMLForms.new(web_cred[:name], web_cred[:baseURL], web_cred[:loginURL], web_cred[:soft403Pattern], web_cred[:id]).object_from_hash(nsc, web_cred)) } site end @@ -516,8 +494,8 @@ def self.json_initializer(data) # @return [Site] Site configuration loaded from a Nexpose console. # def self.copy(connection, id) - site = self.load(connection, id) - site.id = -1 + site = self.load(connection, id) + site.id = -1 site.name = "#{site.name} Copy" site end @@ -536,14 +514,14 @@ def save(connection) resp = AJAX.post(connection, '/api/2.1/site_configurations/', to_json, AJAX::CONTENT_TYPE::JSON) @id = resp.to_i else - resp = AJAX.put(connection, "/api/2.1/site_configurations/#{@id}", to_json, AJAX::CONTENT_TYPE::JSON) + AJAX.put(connection, "/api/2.1/site_configurations/#{@id}", to_json, AJAX::CONTENT_TYPE::JSON) end # Retrieve the scan engine and shared credentials and add them to the site configuration - site_config = Site.load(connection, @id) - @engine_id = site_config.engine_id + site_config = Site.load(connection, @id) + @engine_id = site_config.engine_id @shared_credentials = site_config.shared_credentials - @alerts = site_config.alerts + @alerts = site_config.alerts @id end @@ -592,11 +570,11 @@ class SiteSummary # Constructor # SiteSummary(id, name, description, riskfactor = 1) def initialize(id, name, description = nil, risk_factor = 1.0, risk_score = 0.0) - @id = id - @name = name + @id = id + @name = name @description = description @risk_factor = risk_factor - @risk_score = risk_score + @risk_score = risk_score end end @@ -629,7 +607,7 @@ def as_xml xml.text = @host xml end - alias_method :to_xml_elem, :as_xml + alias to_xml_elem as_xml def to_xml to_xml_elem.to_s @@ -670,14 +648,14 @@ class IPRange # @return [IPRange] an IP address range of one or more addresses. def initialize(from, to = nil) @from = from - @to = to unless from == to + @to = to unless from == to return unless @to.nil? range = IPAddr.new(@from.to_s).to_range unless range.one? @from = range.first.to_s - @to = range.last.to_s + @to = range.last.to_s end end @@ -689,7 +667,7 @@ def initialize(from, to = nil) def size return 1 if @to.nil? from = IPAddr.new(@from) - to = IPAddr.new(@to) + to = IPAddr.new(@to) (from..to).to_a.size end @@ -697,10 +675,10 @@ def size def <=>(other) return 1 unless other.respond_to? :from - from = IPAddr.new(@from) - to = @to.nil? ? from : IPAddr.new(@to) + from = IPAddr.new(@from) + to = @to.nil? ? from : IPAddr.new(@to) cf_from = IPAddr.new(other.from) - cf_to = IPAddr.new(other.to.nil? ? other.from : other.to) + cf_to = IPAddr.new(other.to.nil? ? other.from : other.to) if cf_to < from 1 elsif to < cf_from @@ -721,8 +699,8 @@ def eql?(other) def include?(single_ip) return false unless single_ip.respond_to? :from - from = IPAddr.new(@from) - to = @to.nil? ? from : IPAddr.new(@to) + from = IPAddr.new(@from) + to = @to.nil? ? from : IPAddr.new(@to) other = IPAddr.new(single_ip) if other < from @@ -743,7 +721,7 @@ def as_xml xml.add_attributes({ 'from' => @from, 'to' => @to }) xml end - alias_method :to_xml_elem, :as_xml + alias to_xml_elem as_xml def to_xml as_xml.to_s diff --git a/lib/nexpose/site_credentials.rb b/lib/nexpose/site_credentials.rb index 6ea0f432..0395f2b5 100644 --- a/lib/nexpose/site_credentials.rb +++ b/lib/nexpose/site_credentials.rb @@ -49,7 +49,7 @@ class SiteCredentials < Credential attr_accessor :use_windows_auth # sid for oracle attr_accessor :sid - #for ssh public key require pem format private key + # for ssh public key require pem format private key attr_accessor :pem_format_private_key # for snmp v1/v2 attr_accessor :community_name @@ -71,14 +71,13 @@ def test(nsc, target, engine_id = nil, siteid = -1) unless engine_id engine_id = nsc.engines.detect { |e| e.name == 'Local scan engine' }.id end - @port = Credential::DEFAULT_PORTS[@service] if @port.nil? + @port = Credential::DEFAULT_PORTS[@service] if @port.nil? parameters = _to_param(target, engine_id, @port, siteid) parameters = JSON.generate(parameters) - resp = JSON.parse(Nexpose::AJAX.post(nsc, '/data/credential/test', parameters, Nexpose::AJAX::CONTENT_TYPE::JSON)) + resp = JSON.parse(Nexpose::AJAX.post(nsc, '/data/credential/test', parameters, Nexpose::AJAX::CONTENT_TYPE::JSON)) resp['success'] == 'true' end - def _to_param(target, engine_id, port, siteid) { dev: target, @@ -100,17 +99,17 @@ def _to_param(target, engine_id, port, siteid) } end - #Create a credential object using name, id, description, host and port + # Create a credential object using name, id, description, host and port def self.for_service(name, id = -1, desc = nil, host = nil, port = nil, service = Credential::Service::CIFS) - cred = new - cred.name = name - cred.id = id.to_i - cred.enabled = true - cred.description = desc - cred.host_restriction = host - cred.port_restriction = port - cred.service = service - cred.scope = Credential::Scope::SITE_SPECIFIC + cred = new + cred.name = name + cred.id = id.to_i + cred.enabled = true + cred.description = desc + cred.host_restriction = host + cred.port_restriction = port + cred.service = service + cred.scope = Credential::Scope::SITE_SPECIFIC cred.permission_elevation_type = Credential::ElevationType::NONE cred end @@ -123,7 +122,7 @@ def self.for_service(name, id = -1, desc = nil, host = nil, port = nil, service # @return [SiteCredential] The requested credential of site, if found. # def self.load(nsc, site_id, credential_id) - uri = "/api/2.1/sites/#{site_id}/credentials/#{credential_id}" + uri = "/api/2.1/sites/#{site_id}/credentials/#{credential_id}" resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) hash = JSON.parse(resp, symbolize_names: true) new.object_from_hash(nsc, hash) @@ -187,8 +186,7 @@ def to_h sid: sid, pem_format_private_key: pem_format_private_key, community_name: community_name, - scope: scope - } + scope: scope } end def ==(other) From bb4bf415d66bf6b8f6150ddbc5705733aa38bfd6 Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Tue, 5 Sep 2017 16:35:00 -0700 Subject: [PATCH 09/11] cleanup t,u files --- lib/nexpose/tag.rb | 153 ++++++++++++++++++++---------------------- lib/nexpose/ticket.rb | 87 ++++++++++++------------ lib/nexpose/user.rb | 90 ++++++++++++------------- lib/nexpose/util.rb | 2 +- 4 files changed, 164 insertions(+), 168 deletions(-) diff --git a/lib/nexpose/tag.rb b/lib/nexpose/tag.rb index b1f43f02..6dbe49be 100644 --- a/lib/nexpose/tag.rb +++ b/lib/nexpose/tag.rb @@ -8,13 +8,13 @@ class Connection # def tags tag_summary = [] - tags = JSON.parse(AJAX.get(self, '/api/2.0/tags', AJAX::CONTENT_TYPE::JSON, { per_page: 2_147_483_647 })) + 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 tag_summary end - alias_method :list_tags, :tags + alias list_tags tags # Deletes a tag by ID # @@ -31,13 +31,13 @@ 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: 2_147_483_647 })) + 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 tag_summary end - alias_method :list_asset_tags, :asset_tags + alias list_asset_tags asset_tags # Removes a tag from an asset # @@ -61,7 +61,7 @@ def site_tags(site_id) end tag_summary end - alias_method :list_site_tags, :site_tags + alias list_site_tags site_tags # Removes a tag from a site # @@ -85,8 +85,8 @@ def asset_group_tags(asset_group_id) end tag_summary end - alias_method :group_tags, :asset_group_tags - alias_method :list_asset_group_tags, :asset_group_tags + alias group_tags asset_group_tags + alias list_asset_group_tags asset_group_tags # Removes a tag from an asset_group # @@ -96,7 +96,7 @@ def asset_group_tags(asset_group_id) def remove_tag_from_asset_group(asset_group_id, tag_id) AJAX.delete(self, "/api/2.0/asset_groups/#{asset_group_id}/tags/#{tag_id}") end - alias_method :remove_tag_from_group, :remove_tag_from_asset_group + alias remove_tag_from_group remove_tag_from_asset_group # Returns the criticality value which takes precedent for an asset # @@ -123,7 +123,9 @@ class TagSummary attr_accessor :type def initialize(name, type, id) - @name, @type, @id = name, type, id + @name = name + @type = type + @id = id end def self.parse(json) @@ -154,27 +156,27 @@ module Type # Criticality tag types module Level VERY_HIGH = 'Very High' - HIGH = 'High' - MEDIUM = 'Medium' - LOW = 'Low' - VERY_LOW = 'Very Low' + HIGH = 'High' + MEDIUM = 'Medium' + LOW = 'Low' + VERY_LOW = 'Very Low' end # Tag types module Generic - CUSTOM = 'CUSTOM' - OWNER = 'OWNER' - LOCATION = 'LOCATION' + CUSTOM = 'CUSTOM' + OWNER = 'OWNER' + LOCATION = 'LOCATION' CRITICALITY = 'CRITICALITY' end module Color - BLUE = "#496a77" - DEFAULT = "#f6f6f6" - GREEN = "#7d8a58" - ORANGE = "#de7200" - PURPLE = "#844f7d" - RED = "#a0392e" + BLUE = '#496a77' + DEFAULT = '#f6f6f6' + GREEN = '#7d8a58' + ORANGE = '#de7200' + PURPLE = '#844f7d' + RED = '#a0392e' end end @@ -198,26 +200,28 @@ module Color # Array containing Asset Group IDs to be associated with tag attr_accessor :asset_group_ids - alias_method :group_ids, :asset_group_ids - alias_method :group_ids=, :asset_group_ids= + alias group_ids asset_group_ids + alias group_ids= asset_group_ids= # A TagCriteria attr_accessor :search_criteria def initialize(name, type, id = -1) - @name, @type, @id = name, type, id + @name = name + @type = type + @id = id @source = 'nexpose-client' - @color = @type == Type::Generic::CUSTOM ? Type::Color::DEFAULT : nil + @color = @type == Type::Generic::CUSTOM ? Type::Color::DEFAULT : nil end # Set the color but validate it def color=(hex) - valid_colors = Type::Color::constants.map { |c| Type::Color.const_get(c) } + valid_colors = Type::Color.constants.map { |c| Type::Color.const_get(c) } unless hex.nil? || valid_colors.include?(hex.to_s.downcase) raise ArgumentError, "Unable to set color to an invalid color.\nUse one of #{valid_colors}" - end + end - @color = hex + @color = hex end # Create list of tag objects from hash @@ -233,12 +237,12 @@ def self.load_tags(tags) # Create tag object from hash def self.create(hash) attributes = hash[:attributes] - color = attributes.find { |attr| attr[:tag_attribute_name] == 'COLOR' } - color = color[:tag_attribute_value] if color - source = attributes.find { |attr| attr[:tag_attribute_name] == 'SOURCE' } - source = source[:tag_attribute_value] if source - tag = Tag.new(hash[:tag_name], hash[:tag_type], hash[:tag_id]) - tag.color = color + color = attributes.find { |attr| attr[:tag_attribute_name] == 'COLOR' } + color = color[:tag_attribute_value] if color + source = attributes.find { |attr| attr[:tag_attribute_name] == 'SOURCE' } + source = source[:tag_attribute_value] if source + tag = Tag.new(hash[:tag_name], hash[:tag_type], hash[:tag_id]) + tag.color = color tag.source = source tag end @@ -248,15 +252,9 @@ def to_h tag_id: id, tag_name: name, tag_type: type, - attributes:[ - { - tag_attribute_name: "COLOR", - tag_attribute_value: color - }, - { - tag_attribute_name: "SOURCE", - tag_attribute_value: source - } + attributes: [ + { tag_attribute_name: 'COLOR', tag_attribute_value: color }, + { tag_attribute_name: 'SOURCE', tag_attribute_value: source } ] } end @@ -289,18 +287,15 @@ def self.load(connection, tag_id) end def to_json - json = { - 'tag_name' => @name, - 'tag_type' => @type, - 'tag_id' => @id, - '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_h : nil - } - } + json = { 'tag_name' => @name, + 'tag_type' => @type, + 'tag_id' => @id, + '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_h : nil } } if @type == Type::Generic::CUSTOM json['attributes'] << { 'tag_attribute_name' => 'COLOR', 'tag_attribute_value' => @color } end @@ -316,25 +311,23 @@ def delete(connection) end def self.parse(json) - color = json['attributes'].find { |attr| attr['tag_attribute_name'] == 'COLOR' } - color = color['tag_attribute_value'] if color - source = json['attributes'].find { |attr| attr['tag_attribute_name'] == 'SOURCE' } - source = source['tag_attribute_value'] if source - tag = Tag.new(json['tag_name'], json['tag_type'], json['tag_id']) - tag.color = color - tag.source = source + color = json['attributes'].find { |attr| attr['tag_attribute_name'] == 'COLOR' } + color = color['tag_attribute_value'] if color + source = json['attributes'].find { |attr| attr['tag_attribute_name'] == 'SOURCE' } + source = source['tag_attribute_value'] if source + tag = Tag.new(json['tag_name'], json['tag_type'], json['tag_id']) + tag.color = color + tag.source = source tag.asset_ids = json['asset_ids'] if json['tag_config'] - tag.site_ids = json['tag_config']['site_ids'] + tag.site_ids = json['tag_config']['site_ids'] tag.associated_asset_ids = json['tag_config']['tag_associated_asset_ids'] - tag.asset_group_ids = json['tag_config']['asset_group_ids'] - criteria = json['tag_config']['search_criteria'] - tag.search_criteria = criteria ? Criteria.parse(criteria) : nil + tag.asset_group_ids = json['tag_config']['asset_group_ids'] + criteria = json['tag_config']['search_criteria'] + tag.search_criteria = criteria ? Criteria.parse(criteria) : nil end modifier = json['attributes'].find { |attr| attr['tag_attribute_name'] == 'RISK_MODIFIER' } - if modifier - tag.risk_modifier = modifier['tag_attribute_value'].to_i - end + tag.risk_modifier = modifier['tag_attribute_value'].to_i if modifier tag end @@ -346,9 +339,9 @@ def self.parse(json) # def add_to_asset(connection, asset_id) 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 + 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 # Adds a tag to a site @@ -359,9 +352,9 @@ def add_to_asset(connection, asset_id) # def add_to_site(connection, site_id) 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 + 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 # Adds a tag to an asset group @@ -372,11 +365,11 @@ def add_to_site(connection, site_id) # def add_to_group(connection, group_id) 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 + 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 + alias add_to_asset_group add_to_group private diff --git a/lib/nexpose/ticket.rb b/lib/nexpose/ticket.rb index b4004357..80dd4b32 100644 --- a/lib/nexpose/ticket.rb +++ b/lib/nexpose/ticket.rb @@ -6,7 +6,7 @@ class Connection def list_tickets # TODO: Should take in filters as arguments. xml = make_xml('TicketListingRequest') - r = execute(xml, '1.2') + r = execute(xml, '1.2') tickets = [] if r.success r.res.elements.each('TicketListingResponse/TicketSummary') do |summary| @@ -16,7 +16,7 @@ def list_tickets tickets end - alias_method :tickets, :list_tickets + alias tickets list_tickets # Deletes a Nexpose ticket. # @@ -57,8 +57,8 @@ class TicketSummary # The asset the ticket is created for. attr_accessor :asset_id - alias :device_id :asset_id - alias :device_id= :asset_id= + alias device_id asset_id + alias device_id= asset_id= # The login name of person to whom the ticket is assigned. # The user must have view asset privilege on the asset specified in the asset-id attribute. @@ -78,43 +78,43 @@ class TicketSummary attr_accessor :state def initialize(name, id) - @id, @name = id, name + @id = id + @name = name end def self.parse(xml) - ticket = new(xml.attributes['name'], - xml.attributes['id'].to_i) - ticket.asset_id = xml.attributes['device-id'].to_i - ticket.assigned_to = xml.attributes['assigned-to'] - lookup = Ticket::Priority.constants.reduce({}) { |a, e| a[Ticket::Priority.const_get(e)] = e; a } - ticket.priority = lookup[xml.attributes['priority']] - ticket.author = xml.attributes['author'] - ticket.created_on = DateTime.parse(xml.attributes['created-on']).to_time + ticket = new(xml.attributes['name'], xml.attributes['id'].to_i) + ticket.asset_id = xml.attributes['device-id'].to_i + ticket.assigned_to = xml.attributes['assigned-to'] + lookup = Ticket::Priority.constants.reduce({}) { |a, e| a[Ticket::Priority.const_get(e)] = e; a } + ticket.priority = lookup[xml.attributes['priority']] + ticket.author = xml.attributes['author'] + ticket.created_on = DateTime.parse(xml.attributes['created-on']).to_time ticket.created_on -= ticket.created_on.gmt_offset - lookup = Ticket::State.constants.reduce({}) { |a, e| a[Ticket::State.const_get(e)] = e; a } - ticket.state = lookup[xml.attributes['state']] + lookup = Ticket::State.constants.reduce({}) { |a, e| a[Ticket::State.const_get(e)] = e; a } + ticket.state = lookup[xml.attributes['state']] ticket end module State - OPEN = 'O' - ASSIGNED = 'A' - MODIFIED = 'M' - FIXED = 'X' - PARTIAL = 'P' - REJECTED_FIX = 'R' - PRIORITIZED = 'Z' + OPEN = 'O' + ASSIGNED = 'A' + MODIFIED = 'M' + FIXED = 'X' + PARTIAL = 'P' + REJECTED_FIX = 'R' + PRIORITIZED = 'Z' NOT_REPRODUCIBLE = 'F' - NOT_ISSUE = 'I' - CLOSED = 'C' - UNKNOWN = 'U' + NOT_ISSUE = 'I' + CLOSED = 'C' + UNKNOWN = 'U' end module Priority - LOW = 'low' + LOW = 'low' MODERATE = 'moderate' - NORMAL = 'normal' - HIGH = 'high' + NORMAL = 'normal' + HIGH = 'high' CRITICAL = 'critical' end end @@ -131,11 +131,12 @@ class Ticket < TicketSummary attr_accessor :history def initialize(name, id = nil) - @id, @name = id, name - @priority = Priority::NORMAL + @id = id + @name = name + @priority = Priority::NORMAL @vulnerabilities = [] - @comments = [] - @history = [] + @comments = [] + @history = [] end # Save this ticket to a Nexpose console. @@ -213,7 +214,7 @@ def self.parse_details(xml) ticket.history << Event.parse(entry) end - ticket.comments = ticket.history.select { |h| h.description == 'Added comment' }.map { |e| e.comment } + ticket.comments = ticket.history.select { |h| h.description == 'Added comment' }.map(&:comment) ticket end @@ -232,22 +233,24 @@ class Event attr_accessor :comment def initialize(state, author, created) - @state, @author, @created = state, author, created + @state = state + @author = author + @created = created end def self.parse(xml) - author = xml.attributes['author'] - created_on = DateTime.parse(xml.attributes['created-on']).to_time + author = xml.attributes['author'] + created_on = DateTime.parse(xml.attributes['created-on']).to_time created_on -= created_on.gmt_offset - event = REXML::XPath.first(xml, 'Event') - lookup = Ticket::State.constants.reduce({}) { |a, e| a[Ticket::State.const_get(e)] = e; a } - state = lookup[event.attributes['state']] - desc = event.text + event = REXML::XPath.first(xml, 'Event') + lookup = Ticket::State.constants.reduce({}) { |a, e| a[Ticket::State.const_get(e)] = e; a } + state = lookup[event.attributes['state']] + desc = event.text - event = new(state, author, created_on) + event = new(state, author, created_on) - comment = REXML::XPath.first(xml, 'Comment') + comment = REXML::XPath.first(xml, 'Comment') event.comment = comment.text if comment event.description = desc if desc diff --git a/lib/nexpose/user.rb b/lib/nexpose/user.rb index 5ba7e071..48da084d 100644 --- a/lib/nexpose/user.rb +++ b/lib/nexpose/user.rb @@ -18,7 +18,7 @@ def list_users arr end - alias_method :users, :list_users + alias users list_users # Retrieve the User ID based upon the user's login name. # @@ -47,16 +47,16 @@ class UserSummary attr_reader :is_admin, :is_disabled, :is_locked, :site_count, :group_count def initialize(id, auth_source, auth_module, name, full_name, email, is_admin, is_disabled, is_locked, site_count, group_count) - @id = id + @id = id @auth_source = auth_source @auth_module = auth_module - @name = name - @full_name = full_name - @email = email - @is_admin = is_admin + @name = name + @full_name = full_name + @email = email + @is_admin = is_admin @is_disabled = is_disabled - @is_locked = is_locked - @site_count = site_count + @is_locked = is_locked + @site_count = site_count @group_count = group_count end @@ -97,41 +97,41 @@ class User attr_accessor :all_sites, :all_groups def initialize(name, full_name, password, role_name = 'user', id = -1, enabled = 1, email = nil, all_sites = false, all_groups = false, token = nil) - @name = name - @password = password - @token = token - @role_name = role_name - @authsrcid = ('global-admin'.eql? @role_name) ? '1' : '2' - @id = id - @enabled = enabled - @full_name = full_name - @email = email - @all_sites = all_sites || role_name == 'global-admin' + @name = name + @password = password + @token = token + @role_name = role_name + @authsrcid = 'global-admin'.eql?(@role_name) ? '1' : '2' + @id = id + @enabled = enabled + @full_name = full_name + @email = email + @all_sites = all_sites || role_name == 'global-admin' @all_groups = all_groups || role_name == 'global-admin' - @sites = [] - @groups = [] + @sites = [] + @groups = [] end def to_xml xml = '' @sites.each do |site| - xml << %Q{} + xml << %Q({ }) end @groups.each do |group| - xml << %Q{} + xml << %Q({ }) end xml << '' end @@ -155,22 +155,22 @@ def save(connection) # Issue a UserConfigRequest to load an existing UserConfig from Nexpose. def self.load(connection, user_id) xml = '' r = connection.execute(xml, '1.1') if r.success r.res.elements.each('UserConfigResponse/UserConfig') do |config| - id = config.attributes['id'] - role_name = config.attributes['role-name'] - #authsrcid = config.attributes['authsrcid'] - name = config.attributes['name'] - fullname = config.attributes['fullname'] - - email = config.attributes['email'] - password = config.attributes['password'] - token = config.attributes['token'] - enabled = config.attributes['enabled'].to_i - all_sites = config.attributes['allSites'] == 'true' ? true : false + id = config.attributes['id'] + role_name = config.attributes['role-name'] + # authsrcid = config.attributes['authsrcid'] + name = config.attributes['name'] + fullname = config.attributes['fullname'] + + email = config.attributes['email'] + password = config.attributes['password'] + token = config.attributes['token'] + enabled = config.attributes['enabled'].to_i + all_sites = config.attributes['allSites'] == 'true' ? true : false all_groups = config.attributes['allGroups'] == 'true' ? true : false # Not trying to load sites and groups. # Looks like API currently doesn't return that info to load. diff --git a/lib/nexpose/util.rb b/lib/nexpose/util.rb index 88c2e807..e8a3971f 100644 --- a/lib/nexpose/util.rb +++ b/lib/nexpose/util.rb @@ -30,7 +30,7 @@ def make_xml(name, opts = {}, data = '', append_session_id = true) # '1' if the call succeeded. # def self.success?(xml_string) - xml = ::REXML::Document.new(xml_string.to_s) + xml = ::REXML::Document.new(xml_string.to_s) success = ::REXML::XPath.first(xml, '//@success') !success.nil? && success.value.to_i == 1 end From 4ddf41e40578e312a4c4a7be499f9b2fd279062f Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Tue, 5 Sep 2017 17:10:34 -0700 Subject: [PATCH 10/11] cleanup v,w files --- lib/nexpose/version.rb | 2 +- lib/nexpose/vuln.rb | 88 +++++++++++++++++----------------- lib/nexpose/vuln_def.rb | 14 +++--- lib/nexpose/vuln_exception.rb | 71 ++++++++++++++------------- lib/nexpose/wait.rb | 60 ++++++++++++----------- lib/nexpose/web_credentials.rb | 70 +++++++++++++-------------- 6 files changed, 154 insertions(+), 151 deletions(-) diff --git a/lib/nexpose/version.rb b/lib/nexpose/version.rb index cdb6264a..45f5669c 100644 --- a/lib/nexpose/version.rb +++ b/lib/nexpose/version.rb @@ -1,4 +1,4 @@ module Nexpose # The latest version of the Nexpose gem - VERSION = '7.0.1' + VERSION = '7.0.1'.freeze end diff --git a/lib/nexpose/vuln.rb b/lib/nexpose/vuln.rb index dba9d347..8dfb4ca0 100644 --- a/lib/nexpose/vuln.rb +++ b/lib/nexpose/vuln.rb @@ -20,15 +20,15 @@ def list_vulns(full = false) vulns << XML::VulnerabilitySummary.parse(vuln) else vulns << XML::Vulnerability.new(vuln.attributes['id'], - vuln.attributes['title'], - vuln.attributes['severity'].to_i) + vuln.attributes['title'], + vuln.attributes['severity'].to_i) end end end vulns end - alias_method :vulns, :list_vulns + alias vulns list_vulns # Retrieve a list of the different vulnerability check categories. # @@ -39,7 +39,7 @@ def list_vuln_categories data.map { |c| c['Category'] } end - alias_method :vuln_categories, :list_vuln_categories + alias vuln_categories list_vuln_categories # Retrieve a list of the different vulnerability check types. # @@ -49,7 +49,7 @@ def vuln_types data = DataTable._get_dyn_table(self, '/data/vulnerability/checktypes/dyntable.xml?tableID=VulnCheckCategorySynopsis') data.map { |c| c['Category'] } end - alias_method :list_vuln_types, :vuln_types + alias list_vuln_types vuln_types # Retrieve details for a vulnerability. # @@ -111,7 +111,9 @@ class Vulnerability attr_reader :severity def initialize(id, title, severity) - @id, @title, @severity = id, title, severity.to_i + @id = id + @title = title + @severity = severity.to_i end end @@ -126,10 +128,10 @@ class VulnCheck < Vulnerability attr_reader :check_type def initialize(json) - @id = json['Vuln ID'] - @check_id = json['Vuln Check ID'] - @title = json['Vulnerability'] - @severity = json['Severity'].to_i + @id = json['Vuln ID'] + @check_id = json['Vuln Check ID'] + @title = json['Vulnerability'] + @severity = json['Severity'].to_i @check_type = json['Check Type'] @categories = json['Category'].split(/, */) end @@ -165,15 +167,15 @@ def self.parse_attributes(xml) xml.attributes['severity'].to_i) vuln.pci_severity = xml.attributes['pciSeverity'].to_i - vuln.safe = xml.attributes['safe'] == 'true' # or xml.attributes['safe'] == '1' - vuln.added = Date.parse(xml.attributes['added']) - vuln.modified = Date.parse(xml.attributes['modified']) - vuln.credentials = xml.attributes['requiresCredentials'] == 'true' + vuln.safe = xml.attributes['safe'] == 'true' # or xml.attributes['safe'] == '1' + vuln.added = Date.parse(xml.attributes['added']) + vuln.modified = Date.parse(xml.attributes['modified']) + vuln.credentials = xml.attributes['requiresCredentials'] == 'true' # These three fields are optional in the XSD. - vuln.published = Date.parse(xml.attributes['published']) if xml.attributes['published'] - vuln.cvss_vector = xml.attributes['cvssVector'] if xml.attributes['cvssVector'] - vuln.cvss_score = xml.attributes['cvssScore'].to_f if xml.attributes['cvssScore'] + vuln.published = Date.parse(xml.attributes['published']) if xml.attributes['published'] + vuln.cvss_vector = xml.attributes['cvssVector'] if xml.attributes['cvssVector'] + vuln.cvss_score = xml.attributes['cvssScore'].to_f if xml.attributes['cvssScore'] vuln end @@ -194,16 +196,16 @@ class VulnerabilityDetail < VulnerabilitySummary attr_accessor :solution def initialize(id, title, severity) - @id, @title, @severity = id, title, severity + @id = id + @title = title + @severity = severity @references = [] end def self.parse(xml) - vuln = parse_attributes(xml) - + vuln = parse_attributes(xml) vuln.description = REXML::XPath.first(xml, 'description').text - vuln.solution = REXML::XPath.first(xml, 'solution').text - + vuln.solution = REXML::XPath.first(xml, 'solution').text xml.elements.each('references/reference') do |ref| vuln.references << Reference.new(ref.attributes['source'], ref.text) end @@ -218,7 +220,7 @@ class Reference attr_reader :reference def initialize(source, reference) - @source = source + @source = source @reference = reference end end @@ -251,18 +253,18 @@ class VulnFinding attr_reader :verified def initialize(json) - @id = json['nexVulnID'] - @console_id = json['vulnID'] - @title = json['title'] + @id = json['nexVulnID'] + @console_id = json['vulnID'] + @title = json['title'] @cvss_vector = json['cvssBase'] - @cvss_score = json['cvssScore'] - @risk = json['riskScore'] - @published = Time.at(json['publishedDate'] / 1000) - @severity = json['severity'] - @instances = json['vulnInstanceCount'] - @exploit = json['mainExploit'] - @malware = json['malwareCount'] - @verified = DateTime.iso8601(json['verifiedDate'].slice(0, 15)).to_time if json['verifiedDate'] + @cvss_score = json['cvssScore'] + @risk = json['riskScore'] + @published = Time.at(json['publishedDate'] / 1000) + @severity = json['severity'] + @instances = json['vulnInstanceCount'] + @exploit = json['mainExploit'] + @malware = json['malwareCount'] + @verified = DateTime.iso8601(json['verifiedDate'].slice(0, 15)).to_time if json['verifiedDate'] end end @@ -272,16 +274,16 @@ def initialize(json) # class VulnSynopsis < VulnFinding def initialize(hash) - @id = hash['Vuln ID'].to_i - @title = hash['Vulnerability'] + @id = hash['Vuln ID'].to_i + @title = hash['Vulnerability'] @cvss_vector = hash['CVSS Base Vector'] - @cvss_score = hash['CVSS Score'].to_f - @risk = hash['Risk'].to_f - @published = Time.at(hash['Published On'].to_i / 1000) - @severity = hash['Severity'].to_i - @instances = hash['Instances'].to_i - @exploit = hash['ExploitSource'] - @malware = hash['MalwareSource'] == 'true' + @cvss_score = hash['CVSS Score'].to_f + @risk = hash['Risk'].to_f + @published = Time.at(hash['Published On'].to_i / 1000) + @severity = hash['Severity'].to_i + @instances = hash['Instances'].to_i + @exploit = hash['ExploitSource'] + @malware = hash['MalwareSource'] == 'true' end end diff --git a/lib/nexpose/vuln_def.rb b/lib/nexpose/vuln_def.rb index a5121d37..84a7b744 100644 --- a/lib/nexpose/vuln_def.rb +++ b/lib/nexpose/vuln_def.rb @@ -8,7 +8,7 @@ class Connection # @return [Array[VulnerabilityDefinition]] Collection of vulnerability definitions. # def all_vulns - uri = '/api/2.0/vulnerability_definitions' + uri = '/api/2.0/vulnerability_definitions' resp = AJAX.get(self, uri, AJAX::CONTENT_TYPE::JSON, per_page: 2_147_483_647) json = JSON.parse(resp, symbolize_names: true) json[:resources].map { |e| VulnerabilityDefinition.new.object_from_hash(self, e) } @@ -20,7 +20,7 @@ def all_vulns # @return [Array[VulnerabilityDefinition]] A list of vuln definitions which check the CVE. # def find_vulns_by_cve(cve) - uri = '/api/2.0/vulnerability_definitions' + uri = '/api/2.0/vulnerability_definitions' resp = AJAX.get(self, uri, AJAX::CONTENT_TYPE::JSON, cve: cve) json = JSON.parse(resp, symbolize_names: true) json[:resources].map { |e| VulnerabilityDefinition.new.object_from_hash(self, e) } @@ -40,7 +40,7 @@ def find_vulns_by_cve(cve) # check the vulnerability. # def find_vulns_by_ref(source, id) - uri = '/api/2.0/vulnerability_definitions' + uri = '/api/2.0/vulnerability_definitions' resp = AJAX.get(self, uri, AJAX::CONTENT_TYPE::JSON, @@ -62,10 +62,10 @@ def find_vulns_by_ref(source, id) # the provided value. # def find_vulns_by_title(title, all_words = true) - uri = '/api/2.0/vulnerability_definitions' + uri = '/api/2.0/vulnerability_definitions' params = { title: title, all_words: all_words } - resp = AJAX.get(self, uri, AJAX::CONTENT_TYPE::JSON, params) - json = JSON.parse(resp, symbolize_names: true) + resp = AJAX.get(self, uri, AJAX::CONTENT_TYPE::JSON, params) + json = JSON.parse(resp, symbolize_names: true) json[:resources].map { |e| VulnerabilityDefinition.new.object_from_hash(self, e) } end end @@ -121,7 +121,7 @@ class VulnerabilityDefinition < APIObject # @return [VulnerabilityDefinition] The requested vulnerability definition, if found. # def self.load(nsc, id) - uri = "/api/2.0/vulnerability_definitions/#{id}" + uri = "/api/2.0/vulnerability_definitions/#{id}" resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON) hash = JSON.parse(resp, symbolize_names: true) new.object_from_hash(nsc, hash) diff --git a/lib/nexpose/vuln_exception.rb b/lib/nexpose/vuln_exception.rb index 9a5b46bd..6a5d7e19 100644 --- a/lib/nexpose/vuln_exception.rb +++ b/lib/nexpose/vuln_exception.rb @@ -60,11 +60,9 @@ def list_vuln_exceptions(status = nil) results << ve end results.keep_if { |v| v.status == status } unless status.nil? - return results + results end - - alias_method :vuln_exceptions, :list_vuln_exceptions - + alias vuln_exceptions list_vuln_exceptions # Resubmit a vulnerability exception request with a new comment and reason # after an exception has been rejected. @@ -80,10 +78,10 @@ def list_vuln_exceptions(status = nil) # @return [Boolean] Whether or not the resubmission was valid. # def resubmit_vuln_exception(id, comment, reason = nil) - options = { 'exception-id' => id } + options = { 'exception-id' => id } options['reason'] = reason if reason - xml = make_xml('VulnerabilityExceptionResubmitRequest', options) - comment_xml = make_xml('comment', {}, comment, false) + xml = make_xml('VulnerabilityExceptionResubmitRequest', options) + comment_xml = make_xml('comment', {}, comment, false) xml.add_element(comment_xml) r = execute(xml, '1.2') r.success @@ -115,22 +113,21 @@ def delete_vuln_exception(id) execute(xml, '1.2').success end - private - def is_valid_vuln_exception_status?(status) - return true if status.nil? - valid_status = [] - Nexpose::VulnException::Status.constants.each {|con| valid_status << Nexpose::VulnException::Status.const_get(con) } - valid_status << Nexpose::VulnException::Status.constants.map(&:to_s).map(&:downcase) - valid_status.flatten.map(&:downcase).include?(status.downcase) - end + def is_valid_vuln_exception_status?(status) + return true if status.nil? + valid_status = [] + Nexpose::VulnException::Status.constants.each { |con| valid_status << Nexpose::VulnException::Status.const_get(con) } + valid_status << Nexpose::VulnException::Status.constants.map(&:to_s).map(&:downcase) + valid_status.flatten.map(&:downcase).include?(status.downcase) + end - def status_string_to_constant(status) - Nexpose::VulnException::Status.constants.find do |name| - Nexpose::VulnException::Status.const_get(name).to_s.downcase==status.downcase || status.to_sym.downcase == name.downcase - end + def status_string_to_constant(status) + Nexpose::VulnException::Status.constants.find do |name| + Nexpose::VulnException::Status.const_get(name).to_s.casecmp(status.downcase) || status.to_sym.casecmp(name) end + end end @@ -138,13 +135,13 @@ def status_string_to_constant(status) # # Certain attributes are necessary for some exception scopes, even though # they are optional otherwise. - # • An exception for all instances of a vulnerability on all assets only + # - An exception for all instances of a vulnerability on all assets only # requires the vuln_id attribute. The asset_id, vuln_key and port # attributes are ignored for this scope type. - # • An exception for all instances on a specific asset requires the vuln_id + # - An exception for all instances on a specific asset requires the vuln_id # and asset_id attributes. The vuln_key and port attributes are ignored for # this scope type. - # • An exception for a specific instance of a vulnerability on a specific + # - An exception for a specific instance of a vulnerability on a specific # asset requires the vuln_id, asset_id. Additionally, the port and/or the # key attribute must be specified. # @@ -169,8 +166,8 @@ class VulnException attr_accessor :scope # ID of asset, if this exception applies to only one asset. attr_accessor :asset_id - alias :device_id :asset_id - alias :device_id= :asset_id= + alias device_id asset_id + alias device_id= asset_id= # Id of the site, if this exception applies to all instances on a site attr_accessor :site_id # ID of the Asset Group, if this exception applies to all instances on an asset group @@ -193,9 +190,11 @@ class VulnException # Date when Submit occurred [Time] attr_accessor :submit_date - def initialize(vuln_id, scope, reason, status = nil) - @vuln_id, @scope, @reason, @status = vuln_id, scope, reason, status + @vuln_id = vuln_id + @scope = scope + @reason = reason + @status = status end # Submit this exception on the security console. @@ -413,27 +412,27 @@ def self.parse(xml) # module Status UNDER_REVIEW = 'Under Review' - APPROVED = 'Approved' - REJECTED = 'Rejected' - DELETED = 'Deleted' + APPROVED = 'Approved' + REJECTED = 'Rejected' + DELETED = 'Deleted' end # The reason for the exception status. # module Reason - FALSE_POSITIVE = 'False Positive' + FALSE_POSITIVE = 'False Positive' COMPENSATING_CONTROL = 'Compensating Control' - ACCEPTABLE_USE = 'Acceptable Use' - ACCEPTABLE_RISK = 'Acceptable Risk' - OTHER = 'Other' + ACCEPTABLE_USE = 'Acceptable Use' + ACCEPTABLE_RISK = 'Acceptable Risk' + OTHER = 'Other' end # The scope of the exception. # module Scope - ALL_INSTANCES = 'All Instances' - ALL_INSTANCES_ON_A_SPECIFIC_ASSET = 'All Instances on a Specific Asset' - ALL_INSTANCES_IN_A_SPECIFIC_SITE = 'All Instances in a Specific Site' + ALL_INSTANCES = 'All Instances' + ALL_INSTANCES_ON_A_SPECIFIC_ASSET = 'All Instances on a Specific Asset' + ALL_INSTANCES_IN_A_SPECIFIC_SITE = 'All Instances in a Specific Site' SPECIFIC_INSTANCE_OF_SPECIFIC_ASSET = 'Specific Instance of Specific Asset' end end diff --git a/lib/nexpose/wait.rb b/lib/nexpose/wait.rb index 810fdf23..27cbbbb2 100644 --- a/lib/nexpose/wait.rb +++ b/lib/nexpose/wait.rb @@ -1,12 +1,13 @@ module Nexpose + class Wait attr_reader :error_message, :ready, :retry_count, :timeout, :polling_interval def initialize(retry_count: nil, timeout: nil, polling_interval: nil) - @error_message = 'Default General Failure in Nexpose::Wait' - @ready = false - @retry_count = retry_count.to_i - @timeout = timeout + @error_message = 'Default General Failure in Nexpose::Wait' + @ready = false + @retry_count = retry_count.to_i + @timeout = timeout @polling_interval = polling_interval end @@ -18,49 +19,49 @@ def for_report(nexpose_connection:, report_id:) poller = Nexpose::Poller.new(timeout: @timeout, polling_interval: @polling_interval) poller.wait(report_status_proc(nexpose_connection: nexpose_connection, report_id: report_id)) @ready = true - rescue TimeoutError - @ready = false - retry if timeout_retry? - @error_message = "Timeout Waiting for Report to Generate - Report Config ID: #{report_id}" - rescue NoMethodError => error - @ready = false - @error_message = "Error Report Config ID: #{report_id} :: Report Probably Does Not Exist :: #{error}" - rescue => error - @ready = false - @error_message = "Error Report Config ID: #{report_id} :: #{error}" + rescue Timeout::Error + @ready = false + retry if timeout_retry? + @error_message = "Timeout Waiting for Report to Generate - Report Config ID: #{report_id}" + rescue NoMethodError => error + @ready = false + @error_message = "Error Report Config ID: #{report_id} :: Report Probably Does Not Exist :: #{error}" + rescue => error + @ready = false + @error_message = "Error Report Config ID: #{report_id} :: #{error}" end def for_integration(nexpose_connection:, scan_id:, status: 'finished') poller = Nexpose::Poller.new(timeout: @timeout, polling_interval: @polling_interval) poller.wait(integration_status_proc(nexpose_connection: nexpose_connection, scan_id: scan_id, status: status)) @ready = true - rescue TimeoutError - @ready = false - retry if timeout_retry? - @error_message = "Timeout Waiting for Integration Status of '#{status}' - Scan ID: #{scan_id}" - rescue Nexpose::APIError => error - @ready = false - @error_message = "API Error Waiting for Integration Scan ID: #{scan_id} :: #{error.req.error}" + rescue Timeout::Error + @ready = false + retry if timeout_retry? + @error_message = "Timeout Waiting for Integration Status of '#{status}' - Scan ID: #{scan_id}" + rescue Nexpose::APIError => error + @ready = false + @error_message = "API Error Waiting for Integration Scan ID: #{scan_id} :: #{error.req.error}" end def for_judgment(proc:, desc:) poller = Nexpose::Poller.new(timeout: @timeout, polling_interval: @polling_interval) poller.wait(proc) @ready = true - rescue TimeoutError - @ready = false - retry if timeout_retry? - @error_message = "Timeout Waiting for Judgment to Judge. #{desc}" + rescue Timeout::Error + @ready = false + retry if timeout_retry? + @error_message = "Timeout Waiting for Judgment to Judge. #{desc}" end private def report_status_proc(nexpose_connection:, report_id:) - Proc.new { nexpose_connection.last_report(report_id).status == 'Generated' } + proc { nexpose_connection.last_report(report_id).status == 'Generated' } end def integration_status_proc(nexpose_connection:, scan_id:, status:) - Proc.new { nexpose_connection.scan_status(scan_id).downcase == status.downcase } + proc { nexpose_connection.scan_status(scan_id).casecmp(status) } end def timeout_retry? @@ -71,6 +72,7 @@ def timeout_retry? false end end + end class Poller @@ -89,7 +91,7 @@ def wait(condition) @poll_begin = Time.now loop do break if condition.call - raise TimeoutError if @poll_begin + @timeout < Time.now + raise Timeout::Error if @poll_begin + @timeout < Time.now sleep @polling_interval end end @@ -105,5 +107,7 @@ def set_polling_interval default_polling = 1 ENV['GLOBAL_POLLING_INTERVAL'].nil? ? default_polling : ENV['GLOBAL_POLLING_INTERVAL'] end + end + end diff --git a/lib/nexpose/web_credentials.rb b/lib/nexpose/web_credentials.rb index 9344d8c0..1437ad00 100644 --- a/lib/nexpose/web_credentials.rb +++ b/lib/nexpose/web_credentials.rb @@ -4,14 +4,13 @@ module Nexpose module WebCredentials module WebAppAuthType - HTML_FORM = 'htmlform' # Represent HTML form credentials. + HTML_FORM = 'htmlform' # Represent HTML form credentials. HTTP_HEADER = 'httpheaders' # Represent HTTP header credentials. end # Object that represents Header name-value pairs, associated with Web Session Authentication. # class Header - # Name, one per Header attr_reader :name # Value, one per Header @@ -19,7 +18,7 @@ class Header # Construct with name value pair def initialize(name, value) - @name = name + @name = name @value = value end @@ -28,16 +27,16 @@ def to_json end def to_h - header = Hash.new + header = {} header[@name] = @value header end + end # Object that represents Headers, associated with Web Session Authentication. # class Headers < APIObject - # A regular expression used to match against the response to identify authentication failures. attr_reader :soft403Pattern # Base URL of the application for which the form authentication applies. @@ -48,20 +47,19 @@ class Headers < APIObject attr_reader :name # is this enable for the site configuration attr_accessor :enabled - #service type of header + # service type of header attr_reader :service # id of the header attr_reader :id - def initialize(name, baseURL, soft403Pattern, id = -1, enabled = true) - @headers = {} - @name = name - @baseURL = baseURL + @headers = {} + @name = name + @baseURL = baseURL @soft403Pattern = soft403Pattern - @service = WebAppAuthType::HTTP_HEADER - @enabled = enabled - @id = id + @service = WebAppAuthType::HTTP_HEADER + @enabled = enabled + @id = id end def add_header(header) @@ -79,8 +77,7 @@ def to_h name: name, headers: headers, baseURL: baseURL, - soft403Pattern: soft403Pattern - } + soft403Pattern: soft403Pattern } end def ==(other) @@ -96,7 +93,8 @@ def eql?(other) baseURL.eql?(other.baseURL) && soft403Pattern.eql?(other.soft403Pattern) end - end + + end # When using HTML form, this represents the login form information. # @@ -116,9 +114,9 @@ class Field attr_reader :checked def initialize(name, value, type, dynamic, checked) - @name = name - @value = value - @type = type + @name = name + @value = value + @type = type @dynamic = dynamic @checked = checked end @@ -136,12 +134,12 @@ def to_h checked: checked } end + end # When using HTML form, this represents the login form information. # class HTMLForm - # The name of the form being submitted. attr_reader :name # The HTTP action (URL) through which to submit the login form. @@ -154,11 +152,11 @@ class HTMLForm attr_reader :fields def initialize(name, action, method, encType) - @name = name - @action = action - @method = method + @name = name + @action = action + @method = method @encType = encType - @fields = [] + @fields = [] end def add_field(field) @@ -175,9 +173,9 @@ def to_h method: method, encType: encType, fields: fields, - parentPage: action - } + parentPage: action } end + end # When using HTML form, this represents the login form information. @@ -194,7 +192,7 @@ class HTMLForms < APIObject attr_reader :name # is this enable for the site configuration attr_accessor :enabled - #service type of header + # service type of header attr_reader :service # id of the header attr_reader :id @@ -202,13 +200,13 @@ class HTMLForms < APIObject attr_reader :form def initialize(name, baseURL, loginURL, soft403Pattern, id = -1, enabled = true) - @name = name - @baseURL = baseURL - @loginURL = loginURL + @name = name + @baseURL = baseURL + @loginURL = loginURL @soft403Pattern = soft403Pattern - @service = WebAppAuthType::HTML_FORM - @enabled = enabled - @id = id + @service = WebAppAuthType::HTML_FORM + @enabled = enabled + @id = id end def add_html_form(html_form) @@ -227,8 +225,7 @@ def to_h form: form.to_h, baseURL: baseURL, loginURL: loginURL, - soft403Pattern: soft403Pattern - } + soft403Pattern: soft403Pattern } end def ==(other) @@ -247,6 +244,7 @@ def eql?(other) end end + end -end +end From ed1be661a10b9a9dbf51baba3f441b850b601909 Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Tue, 5 Sep 2017 17:12:56 -0700 Subject: [PATCH 11/11] cleanup filter file --- lib/nexpose/discovery/filter.rb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/nexpose/discovery/filter.rb b/lib/nexpose/discovery/filter.rb index af18c55f..9aa6153a 100644 --- a/lib/nexpose/discovery/filter.rb +++ b/lib/nexpose/discovery/filter.rb @@ -7,20 +7,20 @@ module Field CLUSTER = 'CLUSTER' # Valid Operators: IS, IS_NOT - DATACENTER ='DATACENTER' + DATACENTER = 'DATACENTER' # Valid Operators: CONTAINS, NOT_CONTAINS - GUEST_OS_FAMILY = 'GUEST_OS_FAMILY' #Also AWS Filter + GUEST_OS_FAMILY = 'GUEST_OS_FAMILY' # Also AWS Filter # Valid Operators: IN, NOT_IN - IP_ADDRESS_RANGE = 'IP_ADDRESS' #Also AWS Filter + IP_ADDRESS_RANGE = 'IP_ADDRESS' # Also AWS Filter # Valid Operators: IN, NOT_IN # Valid Values (See Value::PowerState): ON, OFF, SUSPENDED POWER_STATE = 'POWER_STATE' # Valid Operators: CONTAINS, NOT_CONTAINS - RESOURCE_POOL_PATH ='RESOURCE_POOL_PATH' + RESOURCE_POOL_PATH = 'RESOURCE_POOL_PATH' # Valid Operators: IS, IS_NOT, CONTAINS, NOT_CONTAINS, STARTS_WITH VIRTUAL_MACHINE_NAME = 'VM' @@ -45,7 +45,7 @@ module Field INSTANCE_TYPE = 'INSTANCE_TYPE' # Valid Operators: IN, NOT_IN - REGION ='REGION' + REGION = 'REGION' ###### Mobile or Active sync Filters ###### # Valid Operators: CONTAINS, NOT_CONTAINS @@ -54,13 +54,12 @@ module Field # Valid Operators: IS, IS_NOT, CONTAINS, NOT_CONTAINS, STARTS_WITH USER = 'DEVICE_USER_DISPLAY_NAME' - end module Value module PowerState - ON = 'poweredOn' - OFF = 'poweredOff' + ON = 'poweredOn' + OFF = 'poweredOff' SUSPENDED = 'suspended' end end