From 5c4022e29bf46e4ae66db4d527ecd5e039c38496 Mon Sep 17 00:00:00 2001 From: sgreen-r7 Date: Thu, 28 Sep 2017 16:16:31 -0700 Subject: [PATCH 01/58] changelog update and version bump --- CHANGELOG.md | 7 +++++++ lib/nexpose/version.rb | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8c45864..defdc5ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## [v7.1.1](https://github.com/rapid7/nexpose-client/tree/v7.1.1) (2017-09-28) +[Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.1.0...v7.1.1) + +**Merged pull requests:** + +- Some methods were not honoring custom Connection Timeouts [\#300](https://github.com/rapid7/nexpose-client/pull/300) ([sgreen-r7](https://github.com/sgreen-r7)) + ## [v7.1.0](https://github.com/rapid7/nexpose-client/tree/v7.1.0) (2017-09-26) [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.0.1...v7.1.0) diff --git a/lib/nexpose/version.rb b/lib/nexpose/version.rb index 4cbae6d9..490b8733 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.1.1'.freeze + VERSION = '7.1.2'.freeze end From efb262ab0b3b7968e92b28316245fbb5f6cee2a8 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Tue, 3 Oct 2017 16:00:39 -0700 Subject: [PATCH 02/58] Add a method to add common vuln status filters to report configs This is a convenience method for creating reports that should behave the same as reports created in the web UI. --- lib/nexpose/report.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/nexpose/report.rb b/lib/nexpose/report.rb index 953abba4..5a8f2ee7 100644 --- a/lib/nexpose/report.rb +++ b/lib/nexpose/report.rb @@ -207,6 +207,16 @@ def add_filter(type, id) filters << Filter.new(type, id) end + # Add the common vulnerability status filters as used by the UI for most + # report templates (defaults). Recommended for reports that do not require + # 'not vlunerable' results to be included. The following statuses are added: + # vulnerable-exploted, vulnerable-version, and potential. + def add_common_vuln_status_filters + ['vulnerable-exploited', 'vulnerable-version', 'potential'].each do |vuln_status| + filters << Filter.new('vuln-status', vuln_status) + end + end + def to_xml xml = %( Date: Tue, 3 Oct 2017 16:16:14 -0700 Subject: [PATCH 03/58] Update comment to specify which report types are relevant --- lib/nexpose/report.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/nexpose/report.rb b/lib/nexpose/report.rb index 5a8f2ee7..efce709a 100644 --- a/lib/nexpose/report.rb +++ b/lib/nexpose/report.rb @@ -207,10 +207,10 @@ def add_filter(type, id) filters << Filter.new(type, id) end - # Add the common vulnerability status filters as used by the UI for most - # report templates (defaults). Recommended for reports that do not require - # 'not vlunerable' results to be included. The following statuses are added: - # vulnerable-exploted, vulnerable-version, and potential. + # Add the common vulnerability status filters as used by the UI for export + # and jasper report templates (the default filters). Recommended for reports + # that do not require 'not vulnerable' results to be included. The following + # statuses are added: vulnerable-exploted, vulnerable-version, and potential. def add_common_vuln_status_filters ['vulnerable-exploited', 'vulnerable-version', 'potential'].each do |vuln_status| filters << Filter.new('vuln-status', vuln_status) From 617cedff1ec0ca1cfbce81cbb307486dc661f9c3 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Wed, 6 Dec 2017 16:31:35 -0600 Subject: [PATCH 04/58] Port eso-client gem to nexpose-client --- lib/eso.rb | 24 ++ lib/eso/conductor.rb | 227 ++++++++++++++++++ lib/eso/configuration/configuration.rb | 104 ++++++++ .../configuration/configuration_manager.rb | 136 +++++++++++ lib/eso/filter.rb | 137 +++++++++++ lib/eso/integration_option.rb | 88 +++++++ lib/eso/integration_options_manager.rb | 153 ++++++++++++ lib/eso/nexpose.rb | 209 ++++++++++++++++ lib/eso/service.rb | 82 +++++++ lib/eso/step.rb | 166 +++++++++++++ lib/eso/step_configuration.rb | 73 ++++++ lib/eso/version.rb | 3 + lib/eso/workflow.rb | 151 ++++++++++++ 13 files changed, 1553 insertions(+) create mode 100644 lib/eso.rb create mode 100644 lib/eso/conductor.rb create mode 100644 lib/eso/configuration/configuration.rb create mode 100644 lib/eso/configuration/configuration_manager.rb create mode 100644 lib/eso/filter.rb create mode 100644 lib/eso/integration_option.rb create mode 100644 lib/eso/integration_options_manager.rb create mode 100644 lib/eso/nexpose.rb create mode 100644 lib/eso/service.rb create mode 100644 lib/eso/step.rb create mode 100644 lib/eso/step_configuration.rb create mode 100644 lib/eso/version.rb create mode 100644 lib/eso/workflow.rb diff --git a/lib/eso.rb b/lib/eso.rb new file mode 100644 index 00000000..dd1933e0 --- /dev/null +++ b/lib/eso.rb @@ -0,0 +1,24 @@ +require 'date' +require 'json' +require 'net/http' +require 'net/https' +require 'nexpose' +require 'time' +require 'uri' + +require 'eso/conductor' +require 'eso/configuration/configuration' +require 'eso/configuration/configuration_manager' +require 'eso/filter' +require 'eso/integration_option' +require 'eso/integration_options_manager' +require 'eso/nexpose' +require 'eso/service' +require 'eso/step' +require 'eso/step_configuration' +require 'eso/version' +require 'eso/workflow' + +module Eso + +end diff --git a/lib/eso/conductor.rb b/lib/eso/conductor.rb new file mode 100644 index 00000000..694f9c4d --- /dev/null +++ b/lib/eso/conductor.rb @@ -0,0 +1,227 @@ +require 'eso/service' + +module Eso + class Conductor < Service + + # Constructor for Conductor. + # + # @param [String] host Hostname or IP address where this conductor resides. + # @param [Integer] port The TCP port to connect to this conductor on. + # @param [Nexpose::Connection] nsc A logged-in Nexpose::Connection object with a valid session used to authenticate. + # @return [Eso::Conductor] The newly created conductor object + # + def initialize(host:, port: 3780, nsc:) + super(host: host, port: port, nsc: nsc) + @url = "https://#{@host}:#{@port}/eso/conductor-service/api/" + end + + # Return all of the workflows that currently exist on this conductor. + # + # @return [Array] An array containing all of the current workflows on the conductor in Eso::Workflow object format. Returns an empty array if no workflows are present. + # + def workflows + rv = [] + json_data = get(url: "#{@url}workflows/") + json_data.each do |wf| + workflow = Workflow.new(id: wf[:id], name: wf[:name]) + steps = wf[:steps] + steps.each do |step| + workflow_step = Step.new(uuid: step[:uuid], + service_name: step[:serviceName], + workflow: workflow, + type_name: step[:stepConfiguration][:typeName], + previous_type_name: step[:stepConfiguration][:previousTypeName], + configuration_params: step[:stepConfiguration][:configurationParams]) + workflow.steps << workflow_step + end + rv << workflow + end + rv + end + + # Return the workflow histories with only the state histories for the given date range. + # + # @param [Fixnum] starttime The time in milliseconds since epoch for which you want the workflow histories + # @param [Fixnum] endtime The time in milliseconds since epoch for which you want the workflow histories + # @return [Array[Eso::Workflow::History]] An array containing all of the workflow histories from the + # Conductor, which has StateHistory objects containing startTime's within the specified time range. Only the + # StateHistories within that range are returned in the WorkflowHistory object. Returns an empty array if none are present. + def workflow_histories(starttime, endtime) + histories = [] + json_data = get(url: "#{@url}workflows/history/#{starttime}/#{endtime}") + json_data.each do |wf| + # Initialize WorkflowHistory elements + workflow_steps = [] + state_histories = [] + + # Create a new WorkflowHistory with the details we already know + workflow_history = Eso::Workflow::History.new(id: wf[:id], + name: wf[:name], + timeCreated: wf[:timeCreated], + state: wf[:state], + message: wf[:message], + steps: workflow_steps, + history: state_histories + ) + + # Parse the steps out of the response to be returned with the WorkflowHistory + wf[:steps].each do |step| + workflow_steps << Step.new(uuid: step[:uuid], + service_name: step[:serviceName], + workflow: workflow_history, + type_name: step[:stepConfiguration][:typeName], + previous_type_name: step[:stepConfiguration][:previousTypeName], + configuration_params: step[:stepConfiguration][:configurationParams]) + end + workflow_history.steps = workflow_steps + + # Parse the histories out of the response, to be returned with the WorkflowHistory. For some reason. + # this failed with named parameters. For now I returned it to positional. + wf[:history].each do |history| + state_histories << Eso::Workflow::StateHistory.new(history[:message], + history[:state], + history[:startTime]) + end + workflow_history.state_histories = state_histories + + # Add the Workflow History we just built to the list to be returned. + histories << workflow_history + end + histories + end + + # Get the state of the specified workflow. + # + # @param [String] workflow_id The ID of the workflow to retrieve the state of. + # @return [String] The current state of the workflow. + # + def workflow_state(workflow_id:) + get(url: "#{@url}workflows/#{workflow_id}/state") + end + + # Get the count of items in a state of the specified workflow. + # + # @param [Eso::Workflow::State] state The state of the workflows to retrieve the count of. + # @return [Integer] The number of workflows in the requested state. + # + def workflows_state_count(state) + get(url: "#{@url}workflows/count/#{state}") + end + + # Retrieve the states for all of the workflows created on the conductor. + # + # @return [Hash] A hash containing the states of all existing workflows, keyed by workflow ID. + # + def workflow_states + wfs = workflows + states = {} + wfs.each { |wf| states[wf.id] = workflow_state(workflow_id: wf.id) } + states + end + + # Create a new workflow on this conductor. + # + # @param [String] name The user-facing name the workflow will be created with. + # @param [Array] steps An array containing each of the steps that the workflow will be created with, in Eso::Step format. + # @return [Eso::Workflow] The newly created workflow object + # + def create_workflow(name:, steps:) + workflow = Workflow.new(name: name, steps: steps) + + resp = post(url: "#{@url}workflows/", payload: workflow.to_json) + created_workflow = Workflow.load(self, resp[:id]) + + created_workflow + end + + # Update an existing workflow on the conductor to have the configuration of the workflow object passed into this method. + # + # @param [Eso::Workflow] updated_workflow A workflow object that has already had all required changes made to it. This workflow must have an ID set. + # + def update_workflow(updated_workflow:) + payload = updated_workflow.to_json + put(url: "#{@url}workflows/#{updated_workflow.id}", payload: payload) + end + + # Delete an existing workflow from the conductor. + # + # @param [String] workflow_id The ID of the workflow to be deleted. + # + def delete_workflow(workflow_id:) + delete(url: "#{@url}workflows/#{workflow_id}") + end + + # Delete all current workflows on the conductor. + # + def delete_all_workflows + wfs = workflows + wfs.each { |wf| delete_workflow(workflow_id: wf.id) } + end + + # Start the specified workflow. + # + # @param [String] workflow_id The ID of the workflow to be started. + # + def start_workflow(workflow_id:) + post(url: "#{@url}workflows/#{workflow_id}/state") + end + + # Stop the specified workflow. + # + # @param [String] workflow_id The ID of the workflow to be stopped. + # + def stop_workflow(workflow_id:) + delete(url: "#{@url}workflows/#{workflow_id}/state") + end + + # Start all workflows that exist on the conductor. + # + # @return [Hash] A hash containing the states of all existing workflows, keyed by workflow ID. + # + def start_all_workflows + wf_states = workflow_states + + wf_states.each { |wf_id, state| start_workflow(workflow_id: wf_id) if state[:workflow_state] == "STOPPED" } + workflow_states + end + + # Stop all workflows that exist on the conductor. + # + # @return [Hash] A hash containing the states of all existing workflows, keyed by workflow ID. + # + def stop_all_workflows + wf_states = workflow_states + + wf_states.each { |wf_id, state| stop_workflow(workflow_id: wf_id) if state[:workflow_state] == "RUNNING" } + workflow_states + end + + # Returns the translated value of the specified key for a step type (defined in Eso::StepNames). + # The translated value will be based on the language settings the user has configured. + # + # @param [String] step_type The step type to query metadata for. Valid values defined in Eso::StepNames + # @param [String] key The key value in the metadata that maps to the desired label. + # @return [String] The translated value of the key. + # + def get_translation_label(step_type, key) + json_data = get(url: "#{@url}services/nexpose/metadata/#{step_type}") + + target_hash = json_data[:labels].values.find { |label_hash| label_hash.has_key?(key) } + target_hash[key] if target_hash + end + + # Returns the metadata key for a specified translated string. + # The translated value needs to be in language that the user has configured. + # + # @param [String] step_type The step type to query metadata for. Valid values defined in Eso::StepNames + # @param [String] label The translated value of which you are requesting the key for. + # @return [String] The metadata key corresponding to this label. + # + def get_translation_key(step_type, label) + json_data = get(url: "#{@url}services/nexpose/metadata/#{step_type}") + + target_hash = json_data[:labels].values.find { |label_hash| label_hash.values.include?(label) } + target_hash.key(label).to_s if target_hash + end + end +end diff --git a/lib/eso/configuration/configuration.rb b/lib/eso/configuration/configuration.rb new file mode 100644 index 00000000..ccdd82f3 --- /dev/null +++ b/lib/eso/configuration/configuration.rb @@ -0,0 +1,104 @@ +module Eso + # This class represents the Configuration that is sent to the server for new + # style Discovery Connections. + class Configuration + attr_accessor :service_name, :config_name, :config_id, :properties + + def initialize(service_name:, config_name:, properties:[], config_id:) + @service_name = service_name + @config_name = config_name + @properties = properties + @config_id = config_id + end + + # Convert the Configuration to a JSON string for sending to Nexpose + # + # @return [String] A JSON String representation of the Configuration + def to_json + self.to_hash.to_json + end + + # Convert the Configuration to a Hash + # + # @return [Hash] A Hash representation of the Configuration + def to_hash + hash = {:configId => @config_id, + :serviceName => @service_name, + :configName => @config_name, + :configurationAttributes => {:valueClass => 'Object', + :objectType => 'service_configuration', + :properties => []}} + properties.each {|prop| hash[:configurationAttributes][:properties] << prop.to_hash} + end + + # Retrieve a Configuration attribute property value given the name of the property + # + # @param [String] name The name of the property to retrieve + # @return [String] The value of the property + def property(name) + properties.find{|attr| attr.property == name}.value + end + + # Update a Configuration attribute property value given the name of the property + # + # @param [String] name The name of the property to update + # @param [String] value The value of the property to update + # @return [String] The value of the property + def update_property(name, value) + properties.find{|attr| attr.property == name}.value = value + end + + # Load a Configuration object from a Hash + # + # @param [Hash] hash The Hash containing the Configuration object + # @return [Configuration] The Configuration object which was in the Hash + def self.load(hash) + configuration = self.new(service_name: hash[:serviceName], + config_name: hash[:configName], + config_id: hash[:configID]) + hash[:configurationAttributes][:properties].each do |prop| + configuration.properties << ConfigurationAttribute.load(prop) + end + configuration + end + end + + # The ConfigurationAttribute is a property of the Configuration + class ConfigurationAttribute + attr_accessor :property, :value_class, :value + + def initialize(property, value_class, value) + @property = property + @value_class = value_class + @value = value + end + + # Convert the ConfigurationAttribute to a JSON string for sending to Nexpose + # + # @return [String] A JSON String representation of the ConfigurationAttribute + def to_json + self.to_hash.to_json + end + + # Convert the ConfigurationAttribute to a Hash + # + # @return [Hash] A Hash representation of the ConfigurationAttribute + def to_hash + prop = @property.to_sym + hash = {prop => {}} + hash[prop]['valueClass'] = @value_class + hash[prop]['value'] = @value + end + + # Load a ConfigurationAttribute object from an Array + # + # @param [Array] array The Array containing the ConfigurationAttribute object + # @return [ConfigurationAttribute] The ConfigurationAttribute object which was in the Array + def self.load(array) + property = array.first + value_class = array.last['valueClass'] + value = array.last['value'] + self.new(property, value_class, value) + end + end +end diff --git a/lib/eso/configuration/configuration_manager.rb b/lib/eso/configuration/configuration_manager.rb new file mode 100644 index 00000000..190cf36c --- /dev/null +++ b/lib/eso/configuration/configuration_manager.rb @@ -0,0 +1,136 @@ +module Eso +## +# This class represents a configuration manager service, which manages a number of configurations (ie a hostname, +# port, username, and password) used to connect to services, and the services they connect to (ie, ePO, dxl, palo-alto). +# + class ConfigurationManager + attr_accessor :url, :nexpose_console + + ## + # Constructor for ConfigurationManager. + # + # @param [Nexpose::Connection] nsc A logged-in Nexpose::Connection object with a valid session used to authenticate. + # @return [Eso::ConfigurationManager] The newly created configurationManager object + # + def initialize(nsc) + @nexpose_console = nsc + @url = "https://#{nsc.host}:#{nsc.port}/eso/configuration-manager/api/" + end + + ## + # Return all of the services that are currently supported by this configuration manager. + # + # @return [Array] An array containing all of services in the configuration manager in String object form. + # Returns an empty array if no services have been configured. + # + def services + json_data = ::Nexpose::AJAX.get(@nexpose_console, "#{@url}service/", ::Nexpose::AJAX::CONTENT_TYPE::JSON) + JSON.parse(json_data) + end + + ## + # Return all of the configurations of a particular service type. + # + # @param [String] service_name The name of a service to find configurations of. + # @return [Array] An array containing all the configurations of the given service type. + # + def service_configurations(service_name) + json_data = ::Nexpose::AJAX.get(@nexpose_console, + "#{@url}service/configuration/#{service_name}/", + ::Nexpose::AJAX::CONTENT_TYPE::JSON) + JSON.parse(json_data, :symbolize_names => true) + end + + ## + # Return the configuration of a particular service type with a particular name. + # + # @param [String] service_name The name of a service to find configurations of. + # @param [String] config_name The name of the Configuration. + # @return [Eso::Configuration] A Configuration object which matches the service name and config name requested. + def configuration_by_name(service_name, config_name) + service_configs_by_type = service_configurations(service_name) + config_hash = service_configs_by_type.find { |config| config[:configName] == config_name } + Eso::Configuration.load(config_hash) + end + + def configuration_type(service_name:) + json_data = ::Nexpose::AJAX.get(@nexpose_console, + "#{@url}service/configurationType/#{service_name.downcase}", + ::Nexpose::AJAX::CONTENT_TYPE::JSON) + JSON.parse(json_data) + end + + ## + # Get a configuration by id. Runs a GET call against the eso/configuration-manager/api/service/configuration/CONFIGURATION_ID endpoint + # @param [String] configuration_id The id of the configuration to get + # return [JSON] A json object representing a configuration + # TODO : Update to use an Eso::Configuration + def get_configuration(configuration_id) + json_data = ::Nexpose::AJAX.get(@nexpose_console, "#{@url}/service/configuration/id/#{configuration_id}", ::Nexpose::AJAX::CONTENT_TYPE::JSON) + JSON.parse(json_data, :symbolize_names => true) + end + + ## + # Create a new configuration. + # + # @param [String] payload The JSON representation of a configuration. + # @return [Integer] The configID (>= 1) of the newly created configuration. Raises error on failure. + # TODO: Update to use an Eso::Configuration + def post_service_configuration(payload) + # TODO retry if the post fails on timeout + response_body = ::Nexpose::AJAX.post(@nexpose_console, "#{@url}service/configuration", payload, ::Nexpose::AJAX::CONTENT_TYPE::JSON) + config_id = Integer(JSON.parse(response_body)['data']) + raise Exception.new("API returned invalid configID (#{config_id}) while attempting to create configuration.") unless config_id >= 1 + config_id + end + + ## + # Test a configuration. + # + # @param [String] payload The JSON representation of a configuration. + # @return [String] The response from the call or an APIError + # TODO: Update to use an Eso::Configuration + def test_service_configuration(payload) + ::Nexpose::AJAX.post(@nexpose_console, + "#{@url}service/configuration/test", + payload, + ::Nexpose::AJAX::CONTENT_TYPE::JSON) + end + + ## + # Delete a configuration. Runs a DELETE call against the eso/configuration-manager/api/service/configuration/CONFIGURATION_ID endpoint + # + # @param [String] configuration_id The id of the configuration to delete + # return [Boolean] Return true if the api reports a successful delete. Raises an error on failure. + def delete(configuration_id) + response_body = ::Nexpose::AJAX.delete(@nexpose_console, "#{@url}service/configuration/#{configuration_id}") + raise Exception.new("Failed to delete configuration with ID: #{configuration_id}") unless 'success' == response_body + true + end + + ## + # Preview assets for a configuration. Calls a POST to the eso/configuration-manager/api/service/configuration/preview endpoint + # + # @param configuration The configuration to preview + # return [Array] previewed assets + # TODO: Update to use an Eso::Configuration + def preview_assets(configuration) + response_body = ::Nexpose::AJAX.post(@nexpose_console, + "#{@url}service/configuration/preview", + configuration, + ::Nexpose::AJAX::CONTENT_TYPE::JSON) + @preview_assets = JSON.parse(response_body)["previewAssets"] + end + end + + module ConfigManagerMessages + module TestConfig + CONNECTION_SUCCESSFUL = 'The connection to the external service was successful.' + + # Applies to invalid user, password, wrong protocol, can't reach server, bad base or search query + CONNECTION_FAILED = 'The connection to the external service failed.' + + INVALID_FIELDS = 'The configuration had invalid fields.' + end + end +end diff --git a/lib/eso/filter.rb b/lib/eso/filter.rb new file mode 100644 index 00000000..ec992583 --- /dev/null +++ b/lib/eso/filter.rb @@ -0,0 +1,137 @@ +module Eso + class Filter + # These are defined in Eso::Filters which reside in the respective service they are related to. + attr_accessor :type + + # These are the individual filter items + attr_accessor :filter_items + + # Constructor for Filter. + # + # @param [String] type The type of filter this is. They are based on the service this filter exists in. These are defined in Eso::Filters which reside in the respective service they are related to. + # @param [Array] items Array of filters of this type + # @return [Eso::Filter] The newly created filter object + # + def initialize(type:, items: []) + @type = type + @filter_items = items + end + + # Append a filter_item later + def <<(filter_item) + @filter_items << filter_item + end + + def to_json + self.to_hash.to_json + end + + def to_hash + hash = {} + hash[@type.to_sym] = { + valueClass: 'Array', + items: @filter_items.map{|item| item.to_hash} + } + hash + end + alias_method :to_h, :to_hash + + class FilterItem + attr_accessor :type + # Examples are "OR", "IN", "CONTAINS". These should probably be constantized somewhere. + attr_accessor :operator + + # Array containing the values to filter on + attr_accessor :operands + + def initialize(type:, operator:, operands:) + @type = "#{type}_ITEM" + @operator = operator + process_operands(operands) + end + + def process_operands(operands) + @operands = + if ["IS_EMPTY", "IS_NOT_EMPTY"].include? @operator + nil + elsif @type == "#{Eso::Filters::IP_ADDRESS}_ITEM" || + @type == "#{Eso::Filters::IP_RANGE}_ITEM" || + @type == "#{Eso::Filters::OPEN_PORT}_ITEM" || + @type == "#{Eso::Filters::RISK_SCORE}_ITEM" || + @type == "#{Eso::Filters::CVSS_SCORE}_ITEM" + operands.first.split('-') + else + operands + end + + if @operands == nil + return + end + @operands.map! do |value| + # This regex is used to determine if the string is actually a float. + # http://stackoverflow.com/questions/1034418/determine-if-a-string-is-a-valid-float-value + if value =~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/ + if (@type == "#{Eso::Filters::OPEN_PORT}_ITEM") + value.to_i + else + value.to_f + end + # If it's not a float, let's see if it's an integer. + elsif value.to_i.to_s == value + value.to_i + # Guess not, so lets keep the original value. + else + value + end + end + end + + def to_hash + hash = { + valueClass: "Object", + objectType: @type, + properties: { + operator: { + valueClass: "String", + value: @operator + } + } + } + # Currently there are no standards that say how many operands a filter can have + operand_hash = {} + operand_counter = 1 + unless @operands.nil? + @operands.each do |operand| + label = "operand#{operand_counter}".to_sym + + # A correct value class is required because Jackson expects it. + # A Jackson processor for Ruby would probably make this much nicer + # Also, defaulting to Number is probably a bad idea, but based on current possible values in ESO this works. + case operand.class.to_s + + when "String" + value_class = "String" + when "Array" + value_class = "Array" + when "Fixnum" + value_class = "Integer" + else + value_class = "Number" + end + + operand_hash[label] = { + valueClass: value_class, + value: operand + } + operand_counter += 1 + end + + hash[:properties].merge! operand_hash + end + + hash + end + end + end +end + diff --git a/lib/eso/integration_option.rb b/lib/eso/integration_option.rb new file mode 100644 index 00000000..feaa73ed --- /dev/null +++ b/lib/eso/integration_option.rb @@ -0,0 +1,88 @@ +module Eso + + module IntegrationOptionNames + IMPORT_AD_ASSETS = 'import_ad_assets' + IMPORT_EPO_ASSETS = 'import_epo_assets' + SYNC_AZURE_ASSETS = 'sync_azure_assets' + SYNC_AZURE_ASSETS_WITH_TAGS = 'sync_azure_assets_with_tags' + end + + # IntegrationOptionTypes is a way to categorize what various Integration Options do. + module IntegrationOptionTypes + # The IMPORT_TO_SITE Array tracks Integration Options which load Assets into a Site. + IMPORT_TO_SITE = [ + IntegrationOptionNames::IMPORT_AD_ASSETS, + IntegrationOptionNames::IMPORT_EPO_ASSETS, + IntegrationOptionNames::SYNC_AZURE_ASSETS, + IntegrationOptionNames::SYNC_AZURE_ASSETS_WITH_TAGS + ] + end + + class IntegrationOption + attr_accessor :name + attr_accessor :steps + attr_accessor :id + + def initialize(id: nil, name:, steps: []) + @id = id + @name = name + @steps = steps + end + + def site_id=(site_id) + # As of now, the site is always in the last Step of the IntegrationOption. Might change. + @steps.last.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) + end + + def site_id + # As of now, the site is always in the last Step of the IntegrationOption. Might change. + @steps.last.site_id + end + + # Return this object and the associated steps in a digestible JSON format. + # + # @return [String] JSON interpretation of this workflow. + # + def to_json + # Convert Object to Hash + hash = self.to_hash + + # Grab the Step objects and convert to Hashes + steps = hash['steps'] + hashified_steps = [] + steps.each {|step| hashified_steps << step.to_hash} + hash['steps'] = hashified_steps + + # Convert Hash to JSON + hash.to_json + end + + # Return this object as a Hash. The corresponding Steps will still be objects. + # + # @return [Hash] Hash interpretation of this IntegrationOption. + def to_hash + hash = {} + instance_variables.each {|var| hash[var.to_s.delete("@")] = instance_variable_get(var)} + hash + end + + # Load a Hash of an IntegrationOption into an actual IntegrationOption. Probably didn't need to + # break out separately, but might be useful + # + # @param [Hash] raw_integration_option is a Hash representation of an IntegrationOption + # @return [IntegrationOption] The IntegrationOption version of the Hash + def self.load(raw_integration_option) + integration_option = IntegrationOption.new(id: raw_integration_option[:id], name: raw_integration_option[:name]) + steps = raw_integration_option[:steps] + steps.each do |step| + step_config = step[:stepConfiguration] + integration_option.steps << Step.new(uuid: step[:uuid], + service_name: step[:serviceName], + type_name: step_config[:typeName], + previous_type_name: step_config[:previousTypeName], + configuration_params: step_config[:configurationParams]) + end + integration_option + end + end +end diff --git a/lib/eso/integration_options_manager.rb b/lib/eso/integration_options_manager.rb new file mode 100644 index 00000000..eb0a3f37 --- /dev/null +++ b/lib/eso/integration_options_manager.rb @@ -0,0 +1,153 @@ +require 'nexpose' + +module Eso + ## + # This class is a manager for the integration options api. Integration options match epo/dxl/etc steps + # (ie discover-epo-assets) to nexpose steps (ie import-external-assets). + + class IntegrationOptionsManager + + ## + # Constructor for IntegrationOptionsManager. + # + # @param [Nexpose::Connection] nsc A logged-in Nexpose::Connection object with a valid session used to authenticate. + # @return [Eso::IntegrationOptionsManager] The newly created IntegrationOptionManager object + # + def initialize(nsc) + @nexpose_console = nsc + @url = "https://#{nsc.host}:#{nsc.port}/eso/integration-manager-service/api/integration-options/" + end + + ## + # Create a new or Update existing integration option. + # + # @param [String] payload The JSON representation of an integration option. + # @return [String] The integrationOptionID (a UUID) of the newly created configuration. Raises error on failure. + # + def create(payload) + # TODO retry if the post fails on timeout + response_body = ::Nexpose::AJAX.post(@nexpose_console, "#{@url}", payload, ::Nexpose::AJAX::CONTENT_TYPE::JSON) + JSON.parse(response_body)['data']['id'] + end + alias_method :update, :create + + # Deleting and stopping are the same thing + def delete(integration_option_id) + ::Nexpose::AJAX.delete(@nexpose_console, "#{@url}#{integration_option_id}/state") + end + alias_method :stop, :delete + + ## + # Get an existing integration option. + # + # @param [String] integration_option_id The integration_option_id of the integration option. + # @return IntegrationOption for that id, or nil + # + def get(integration_option_id) + # Gets all integration options + response_body = ::Nexpose::AJAX.get(@nexpose_console, "#{@url}", ::Nexpose::AJAX::CONTENT_TYPE::JSON) + response = JSON.parse(response_body, symbolize_names: true) + + # Find the desired one + raw_integration_option = response.find{|raw| raw[:id] == integration_option_id} + raise "No IntegrationOption with ID #{integration_option_id}" if raw_integration_option.nil? + + # Load it to an object + IntegrationOption.load(raw_integration_option) + end + + ## + # Get the status of an integration option. + # + # @param [String] integration_option_id The integration_option_id of the integration option. + # @return the state (READY, STOPPED, etc) + # + def status(integration_option_id) + response_body = ::Nexpose::AJAX.get(@nexpose_console, "#{@url}#{integration_option_id}/status", ::Nexpose::AJAX::CONTENT_TYPE::JSON) + response = JSON.parse(response_body) + response['state'] + end + + def start(integration_option_id) + response_body = ::Nexpose::AJAX.post(@nexpose_console, "#{@url}#{integration_option_id}/state", ::Nexpose::AJAX::CONTENT_TYPE::JSON) + JSON.parse(response_body) + end + + # TODO: These build_* methods must die. + def self.build_import_epo_assets_option(name:, discovery_conn_id:, site_id: nil) + step1 = Step.new(service_name: ServiceNames::EPO, type_name: StepNames::DISCOVER_EPO) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::IMPORT_EXTERNAL, previous_type_name: step1.type_name) + + #This isn't always known immediately, which is why we have IntegrationOption.site_id= + step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id + IntegrationOption.new(name: name, steps: [step1, step2]) + end + + def self.build_import_ad_assets_option(name:, discovery_conn_id:, site_id: nil) + step1 = Step.new(service_name: ServiceNames::ACTIVE_DIRECTORY, type_name: StepNames::DISCOVER_ACTIVE_DIRECTORY) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::IMPORT_EXTERNAL, previous_type_name: step1.type_name) + + #This isn't always known immediately, which is why we have IntegrationOption.site_id= + step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id + IntegrationOption.new(name: name, steps: [step1, step2]) + end + + def self.build_sync_aws_assets_option(name:, discovery_conn_id:, site_id: nil) + step1 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::DISCOVER_AWS_ASSETS) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::SYNC_EXTERNAL, previous_type_name: step1.type_name) + + #This isn't always known immediately, which is why we have IntegrationOption.site_id= + step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id + IntegrationOption.new(name: name, steps: [step1, step2]) + end + + def self.build_sync_azure_assets_option(name:, discovery_conn_id:, site_id: nil) + step1 = Step.new(service_name: ServiceNames::AZURE, type_name: StepNames::DISCOVER_AZURE_ASSETS) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::SYNC_EXTERNAL, previous_type_name: step1.type_name) + + #This isn't always known immediately, which is why we have IntegrationOption.site_id= + step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id + IntegrationOption.new(name: name, steps: [step1, step2]) + end + + def self.build_sync_azure_assets_with_tags_option(name:, discovery_conn_id:, site_id: nil, tags: '') + step1 = Step.new(service_name: ServiceNames::AZURE, type_name: StepNames::DISCOVER_AZURE_ASSETS) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + .add_property(StepConfiguration::ConfigParamProperties::IMPORT_TAGS, true) + .add_property(StepConfiguration::ConfigParamProperties::EXCLUDE_ASSETS_WITH_TAGS, "") + .add_property(StepConfiguration::ConfigParamProperties::ONLY_IMPORT_THESE_TAGS, tags) + step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::SYNC_EXTERNAL, previous_type_name: step1.type_name) + + #This isn't always known immediately, which is why we have IntegrationOption.site_id= + step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id + IntegrationOption.new(name: name, steps: [step1, step2]) + end + + def self.build_export_risk_scores_option(name:, discovery_conn_id:) + step1 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::RISK_SCORE_UPDATED) + step2 = Step.new(service_name: ServiceNames::EPO, type_name: StepNames::PUSH_RISK_SCORE, previous_type_name: step1.type_name) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + IntegrationOption.new(name: name, steps: [step1, step2]) + end + + def self.build_find_vuln_details_option(name:, discovery_conn_id:) + step1 = Step.new(service_name: ServiceNames::DXL, type_name: StepNames::VULN_DETAILS_REQUEST) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::VULN_DETAILS, previous_type_name: step1.type_name) + step3 = Step.new(service_name: ServiceNames::DXL, type_name: StepNames::VULN_DETAILS_REQUEST, previous_type_name: step2.type_name) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + IntegrationOption.new(name: name, steps: [step1, step2, step3]) + end + + def self.build_publish_vulnerabilities_option(name:, discovery_conn_id:) + step1 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::NEW_ASSET_VULN) + step2 = Step.new(service_name: ServiceNames::DXL, type_name: StepNames::PUBLISH_VULN_INT_TYPE, previous_type_name: step1.type_name) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + IntegrationOption.new(name: name, steps: [step1, step2]) + end + end +end diff --git a/lib/eso/nexpose.rb b/lib/eso/nexpose.rb new file mode 100644 index 00000000..e151790c --- /dev/null +++ b/lib/eso/nexpose.rb @@ -0,0 +1,209 @@ +require 'nexpose' + +module Eso + module ServiceNames + ACTIVE_DIRECTORY = 'active-directory' + AWS = 'amazon-web-services' + AZURE = 'azure' + DXL = 'dxl' + EPO = 'epo' + NEXPOSE = 'nexpose' + end + + module StepNames + ADD_TO_SITE = 'add-to-site' + ADD_VULN_AND_SCAN = 'add-vulnerabilities-to-site-and-scan' + DISCOVER_ACTIVE_DIRECTORY = 'discover-ad-assets' + DISCOVER_AWS_ASSETS = 'discover-aws-assets' + DISCOVER_AZURE_ASSETS = 'discover-azure-assets' + DISCOVER_EPO = 'discover-epo-assets' + DISCOVER_KNOWN = 'discover-known-assets' + DISCOVER_NEW = 'discover-new-assets' + DISCOVERY_CONFIG_METADATA = 'discoveryConfigMetadata' + EMPTY = '' + FILE_REPUTATION_TRIGGER = 'tie-file-reputation-trigger' + IMPORT_EXTERNAL = 'import-external-assets' + NEW_ASSET_VULN = 'new-asset-vulnerability' + NEW_VULN = 'new-vulnerabilities' + PUBLISH_VULN_INT_TYPE = 'publish-vulnerability-integration-type' + PUSH_RISK_SCORE = 'push-risk-score' + RISK_SCORE_UPDATED = 'risk-score-updated' + SCAN = 'scan' + SCAN_IN_SITE = 'scan-in-site' + SYNC_EXTERNAL = 'sync-external-assets' + TAG = 'tag' + VULN_DETAILS = 'vulnerability-details' + VULN_DETAILS_REQUEST = 'vulnerability-details-request' + end + + module Values + ARRAY = 'Array' + BOOLEAN = 'Boolean' + INTEGER = 'Integer' + OBJECT = 'Object' + STRING = 'String' + end + + module StepConfigTypes + DISCOVERY_CONFIG = [StepNames::DISCOVER_ACTIVE_DIRECTORY, + StepNames::DISCOVER_AWS_ASSETS, + StepNames::DISCOVER_AZURE_ASSETS, + StepNames::DISCOVER_EPO, + StepNames::DISCOVER_KNOWN, + StepNames::DISCOVER_NEW, + StepNames::FILE_REPUTATION_TRIGGER, + StepNames::PUBLISH_VULN_INT_TYPE, + StepNames::PUSH_RISK_SCORE, + StepNames::VULN_DETAILS_REQUEST] + EMPTY = [StepNames::NEW_ASSET_VULN, + StepNames::NEW_VULN, + StepNames::RISK_SCORE_UPDATED, + StepNames::VULN_DETAILS] + SITE = [StepNames::ADD_TO_SITE, + StepNames::ADD_VULN_AND_SCAN, + StepNames::IMPORT_EXTERNAL, + StepNames::SCAN, + StepNames::SCAN_IN_SITE, + StepNames::SYNC_EXTERNAL] + TAG = [StepNames::TAG] + end + + module Filters + CVSS_SCORE = 'CVSS_SCORE' + DHCP_HOST_NAME = 'DHCP_HOST_NAME' + HOURS_SINCE_LAST_SCAN= 'HOURS_SINCE_LAST_SCAN' + HOURS_SINCE_LAST_SCAN_ITEM = 'HOURS_SINCE_LAST_SCAN_ITEM' + IP_ADDRESS = 'IP_ADDRESS' + IP_RANGE = 'IP_RANGE' + MAC_ADDRESS = 'MAC_ADDRESS' + OPEN_PORT = 'OPEN_PORT' + RISK_SCORE = 'RISK_SCORE' + SERVICE_NAME = 'SERVICE_NAME' + end + + module Nexpose + def self.create_discovery_workflow(conductor:, name:, step1_type:, step1_param: nil, step2_type:, step2_param:) + step1 = self.send("create_#{step1_type.to_s.gsub(/-/, "_")}_step", id: step1_param) + step2 = self.send("create_#{step2_type.to_s.gsub(/-/, "_")}_step", id: step2_param) + step2.previous_type_name = step1.type_name + conductor.create_workflow(name: name, steps: [step1, step2]) + end + + def self.create_scan_new_vuln_workflow(conductor:, name:, filters:, site_id:) + step1 = self.create_new_vuln_step(workflow: nil, filters: filters, previous_type_name: StepNames::EMPTY) + step2 = self.create_add_vuln_and_scan_step(id: site_id) + step2.previous_type_name = step1.type_name + conductor.create_workflow(name: name, steps: [step1, step2]) + end + + def self.create_file_trigger_workflow(conductor:, name:, step1_param:, step2_param:) + step1 = self.create_file_reputation_step(workflow: nil, id: step1_param) + step2 = self.create_tag_step(workflow: nil, id: step2_param) + step2.previous_type_name = step1.type_name + conductor.create_workflow(name: name, steps: [step1, step2]) + end + + def self.create_scan_in_site_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY) + Step.new(workflow: workflow, + service_name: ServiceNames::NEXPOSE, + type_name: StepNames::SCAN_IN_SITE, + previous_type_name: previous_type_name) + .add_property(StepConfiguration::ConfigParamProperties::SITE_ID, id) + end + + def self.create_file_reputation_step(workflow: nil, id:) + Step.new(workflow: workflow, + service_name: ServiceNames::DXL, + type_name: StepNames::FILE_REPUTATION_TRIGGER, + previous_type_name: nil) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, id) + end + + def self.create_discover_new_assets_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY) + Step.new(workflow: workflow, + service_name: ServiceNames::NEXPOSE, + type_name: StepNames::DISCOVER_NEW, + previous_type_name: previous_type_name) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, id) + end + + def self.create_discover_known_assets_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY) + step = Step.new(workflow: workflow, + service_name: ServiceNames::NEXPOSE, + type_name: StepNames::DISCOVER_KNOWN, + previous_type_name: previous_type_name) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, id) + config_params = step.configuration_params + config_params[:HOURS_SINCE_LAST_SCAN] = { + :valueClass => Values::ARRAY, + :items => [ + { + :valueClass => Values::OBJECT, + :objectType => Filters::HOURS_SINCE_LAST_SCAN_ITEM, + :properties => { + :operator => { + :valueClass => Values::STRING, + :value => ::Nexpose::Search::Operator::GREATER_THAN + }, + :operand1 => { + :valueClass => Values::STRING, + :value => '1' + } + } + } + ] + } + step.configuration_params = config_params + step + end + + def self.create_new_vuln_step(workflow: nil, filters:, previous_type_name: StepNames::EMPTY) + # The filter definitions on the server are not standard at this point so that is why it is necessary to hard code this + # Opening a defect to fix the consistency on these on the backend so we can use the add_filter function in the automation + step = Step.new(workflow: workflow, + service_name: ServiceNames::NEXPOSE, + type_name: StepNames::NEW_VULN, + previous_type_name: previous_type_name) + + filters.each { |filter| step.add_filter(filter) } + step + end + + def self.create_add_vuln_and_scan_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY) + Step.new(workflow: workflow, + service_name: ServiceNames::NEXPOSE, + type_name: StepNames::ADD_VULN_AND_SCAN, + previous_type_name: previous_type_name) + .add_property(StepConfiguration::ConfigParamProperties::SITE_ID, id) + end + + def self.create_add_to_site_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY) + Step.new(workflow: workflow, + service_name: ServiceNames::NEXPOSE, + type_name: StepNames::ADD_TO_SITE, + previous_type_name: previous_type_name) + .add_property(StepConfiguration::ConfigParamProperties::SITE_ID, id) + end + + def self.create_scan_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY) + Step.new(workflow: workflow, + service_name: ServiceNames::NEXPOSE, + type_name: StepNames::SCAN, + previous_type_name: previous_type_name) + .add_property(StepConfiguration::ConfigParamProperties::SITE_ID, id) + end + + def self.create_tag_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY) + Step.new(workflow: workflow, + service_name: ServiceNames::NEXPOSE, + type_name: StepNames::TAG, + previous_type_name: previous_type_name) + .add_property(StepConfiguration::ConfigParamProperties::TAG_ID, id) + end + + def self.get_discover_step(workflow: ) + workflow.get_step(StepNames::DISCOVER_NEW) || workflow.get_step(StepNames::DISCOVER_KNOWN) + end + end +end + diff --git a/lib/eso/service.rb b/lib/eso/service.rb new file mode 100644 index 00000000..ae9d36ce --- /dev/null +++ b/lib/eso/service.rb @@ -0,0 +1,82 @@ +module Eso + class Service + attr_accessor :host + + attr_accessor :port + + attr_accessor :url + + CONTENT_TYPE_JSON = 'application/json; charset-utf-8' + + def initialize(host:, port: 3780, nsc:) + @host = host + @port = port + @nexpose_console = nsc + end + + def get(url:, content_type: CONTENT_TYPE_JSON) + get = Net::HTTP::Get.new(url) + get.set_content_type(content_type) + request(request: get) + end + + def put(url:, payload:, content_type: CONTENT_TYPE_JSON) + put = Net::HTTP::Put.new(url) + put.set_content_type(content_type) + put.body = payload.to_s if payload + request(request: put) + end + + def post(url:, payload: nil, content_type: CONTENT_TYPE_JSON) + post = Net::HTTP::Post.new(url) + post.set_content_type(content_type) + post.body = payload.to_s if payload + request(request: post) + end + + def delete(url:, content_type: CONTENT_TYPE_JSON) + delete = Net::HTTP::Delete.new(url) + delete.set_content_type(content_type) + request(request: delete) + end + + def http(timeout:) + http = Net::HTTP.new(@host, @port) + http.read_timeout = timeout if timeout + http.use_ssl = false + http + end + + def https(timeout:) + http = Net::HTTP.new(@host, @port) + http.read_timeout = timeout if timeout + http.use_ssl = true + http.verify_mode = OpenSSL::SSL::VERIFY_NONE + http + end + + def add_nexpose_session(request:) + request.add_field('nexposeCCSessionID', @nexpose_console.session_id) + request.add_field('Cookie', "nexposeCCSessionID=#{@nexpose_console.session_id}") + end + + def request(request:, timeout: nil) + http = https(timeout: timeout) + add_nexpose_session(request: request) + response = http.request(request) + case response + when Net::HTTPOK, Net::HTTPCreated + rv = nil + if response.content_type == "application/json" && !response.body.empty? + json_data = JSON.parse(response.body, symbolize_names: true) + json_data[:data].nil? ? rv = json_data : rv = json_data[:data] + end + rv + when Net::HTTPForbidden + raise "Access denied. Response was #{response.body}" + else + raise "There was an error sending the request. Response was #{response.body}" + end + end + end +end \ No newline at end of file diff --git a/lib/eso/step.rb b/lib/eso/step.rb new file mode 100644 index 00000000..8e2929c9 --- /dev/null +++ b/lib/eso/step.rb @@ -0,0 +1,166 @@ +module Eso + # Object representation of a step, which are attributes of Workflows and Integration Options + # + class Step + # UUID of this step. This is generated on creation on the server. + attr_accessor :uuid + + # Type of this step. Should be one of Eso::ServiceNames + attr_accessor :serviceName + + # The configuration for this step. + attr_accessor :stepConfiguration + + # Constructor for Step. + # + # @param [String] uuid UUID of this Step. This is created on the server side upon creation through the API. + # @param [String] service_name The name of step this is. + # @param [Workflow] workflow The workflow this step belongs to. + # @param [Hash] configuration_params Hash of the parameters for this step. + # + def initialize(uuid: nil, service_name:, workflow: nil, type_name:, previous_type_name: StepNames::EMPTY, configuration_params: nil) + @uuid = uuid if uuid + @serviceName = service_name + @stepConfiguration = StepConfiguration.new(type_name, previous_type_name) + @stepConfiguration.configurationParams = configuration_params if configuration_params + @stepConfiguration.workflowID = workflow.id if workflow + end + + # Return the configuration parameters for this step. + # + # @return [Hash] Hash of the configuration parameters for this step. + # + def configuration_params + @stepConfiguration.configurationParams + end + + # Set the the configuration parameters for this step. + # + # @param [Hash] config_params of the new configuration parameters you would like to set. + # @return [Hash] Hash of the updated configuration parameters for this step. + # + def configuration_params=(config_params) + @stepConfiguration.configurationParams = config_params + end + + # Return the type name for this step. + # + # @return [String] The currently configured type name. + # + def type_name + @stepConfiguration.typeName + end + + # Set the type name for this step. + # + # @param [String] The new type_name that you would like to set this to. See Eso::StepNames for valid names. + # @return [String] The newly set type name. + # + def type_name=(wf_action_name) + @stepConfiguration.typeName = wf_action_name + end + + # Return the previous type name for this step. + # + # @return [String] The previous type name for this step. + # + def previous_type_name + @stepConfiguration.previousTypeName + end + + # Set the previous type name for this step. + # + # @param [String] The new previous type name that you would like to set. See Eso::StepNames for valid names. + # @return [String] Hash of the configuration parameters for this step. + # + def previous_type_name=(action_name) + @stepConfiguration.previousTypeName = action_name + end + + # Return the properties of this step. + # + # @return [Hash{}] Hash of the properties for this step. + # + def properties + @stepConfiguration.configurationParams[:properties] + end + + # Set the properties of this step. + # + # @param [Hash] The new properties to set for this step. + # @return [Hash] Hash of the newly configured properties for this step. + # + def properties=(new_properties) + @stepConfiguration.configurationParams[:properties] = new_properties + end + + # Determine the siteID of this step, if it exists + # + # @return [String|nil] The String siteID value or nil if no siteID + def site_id + if @stepConfiguration.configurationParams[:properties][:siteID] + @stepConfiguration.configurationParams[:properties][:siteID][:value] + end + end + + # Returns all configured filters for this step. + # + # @return [Array] An array of the currently configured filters for this step, each represented as a hash. + # + def filters + rv = {} + self.properties.each_pair do |key, value| + if value[:properties] + rv[key] = value if value[:properties].has_key?(:operators) + end + end + rv + end + + # Convenience method which calls the #add_property method of the @stepConfiguration, but returns the Step + # + # @return [Step] Returns this Step for chaining + def add_property(name, value) + @stepConfiguration.add_property(name, value) + self + end + + # Convenience method which calls the #add_property method of the @stepConfiguration, but returns the Step + # + # @return [Step] Returns this Step for chaining + def update_property(name, value) + @stepConfiguration.add_property(name, value) + self + end + + # Add the specified filter to this step. The filter is converted to a hash and saved as such instead of being saved as a ESO::Filter object. + # + # @param [Filter] filter The filter to add to this step. + # + def add_filter(filter) + @stepConfiguration.configurationParams[:properties].merge! filter.to_hash + end + + # Return this step in a JSON digestible format. + # + # @return [String] JSON interpretation of this step. + # + def to_json + self.to_hash.to_json + end + + # Return this step as a hash. + # + # @return [Hash] Hash interpretation of this step. + # + def to_hash + hash = {} + instance_variables.each do |var| + value = instance_variable_get(var) + value = value.to_h if value.respond_to?('to_h') + hash[var.to_s.delete('@')] = value + end + hash + end + end +end diff --git a/lib/eso/step_configuration.rb b/lib/eso/step_configuration.rb new file mode 100644 index 00000000..038ba4ff --- /dev/null +++ b/lib/eso/step_configuration.rb @@ -0,0 +1,73 @@ +module Eso + class StepConfiguration + attr_accessor :typeName, :previousTypeName, :configurationParams, :workflowID + + module ConfigParamProperties + DISCOVERY_CONFIG_ID = 'discoveryConfigID' + EXCLUDE_ASSETS_WITH_TAGS= 'excludeAssetsWithTags' + IMPORT_TAGS = 'importTags' + ONLY_IMPORT_THESE_TAGS = 'onlyImportTheseTags' + SITE_ID = 'siteID' + TAG_ID = 'tagID' + end + + module ConfigParamPropertyTypes + BOOLEAN = [ConfigParamProperties::IMPORT_TAGS] + INTEGER = [ConfigParamProperties::DISCOVERY_CONFIG_ID, + ConfigParamProperties::SITE_ID, + ConfigParamProperties::TAG_ID] + STRING = [ConfigParamProperties::EXCLUDE_ASSETS_WITH_TAGS, + ConfigParamProperties::ONLY_IMPORT_THESE_TAGS] + end + + def initialize (typeName, previousTypeName, configurationParams=nil, workflowID=nil) + @typeName = typeName + @previousTypeName = previousTypeName + @configurationParams = configurationParams ? configurationParams : { + :valueClass => Values::OBJECT, + :objectType => typeName, + :properties => {}} + @workflowID = workflowID if workflowID + end + + # This adds the specified property to this StepConfiguration.configurationParams.properties Hash + # + # @param [String] name The name of the property to add, which should be one of ConfigParamProperties + # @param [Object] value The value of the property to add, which should already be in the appropriate format (Eso::Values) + # @return [StepConfiguration] Returns this object for chaining. + def add_property(name, value) + @configurationParams[:properties][name] = + case name + when *ConfigParamPropertyTypes::BOOLEAN + { + valueClass: Values::BOOLEAN, + value: value + } + when *ConfigParamPropertyTypes::INTEGER + { + valueClass: Values::INTEGER, + value: value + } + when *ConfigParamPropertyTypes::STRING + { + valueClass: Values::STRING, + value: value + } + else + raise ArgumentError, "Invalid StepConfiguration ConfigurationParameter Property name: #{name}. " + + 'Should be one of StepConfiguration::ConfigParamProperties' + end + self + end + + def to_h + hash = { + :typeName => @typeName, + :previousTypeName => @previousTypeName, + :configurationParams => @configurationParams + } + hash['workflowID'] = @workflowID if @workflowID + hash + end + end +end diff --git a/lib/eso/version.rb b/lib/eso/version.rb new file mode 100644 index 00000000..edbef1dd --- /dev/null +++ b/lib/eso/version.rb @@ -0,0 +1,3 @@ +module Eso + VERSION = '2.2.1' +end diff --git a/lib/eso/workflow.rb b/lib/eso/workflow.rb new file mode 100644 index 00000000..bdcd1b40 --- /dev/null +++ b/lib/eso/workflow.rb @@ -0,0 +1,151 @@ +module Eso + + # The following classes have mixed casing (snake and camel) to accommodate for the API. + # I guess a TODO would be to write a helper to automatically convert them. + class Workflow + # The id of the workflow. This will be created upon saving to the server upon creation. + attr_accessor :id + + # The name of the workflow. This is required. + attr_accessor :name + + # An array of the steps this workflow takes action on. + attr_accessor :steps + + # The time the workflow was created in milliseconds since epoch + attr_accessor :timeCreated + + + # Constructor for the workflow + # + # @param [String] id ID of the workflow. + # @param [String] name Name of the workflow. + # @param [Array] steps Array of the steps that this workflow takes. + # @param [Fixnum] timeCreated The time the workflow was created in millis since epoch + # + def initialize(id: nil, name:, steps: [], timeCreated: (Time.now.strftime('%s').to_i * 1000) ) + @id = id + @name = name + @steps = steps + @timeCreated = timeCreated + end + + # Load an existing workflow from the API. + # + # @param [Conductor] conductor The Conductor object governing the workflows + # @param [String] id ID of the workflow to load + # @return [Workflow] Workflow object that was loaded. + # + def self.load(conductor, id) + uri = "#{conductor.url}workflows/#{id}" + resp = conductor.get(url: uri) + workflow = self.new(id: resp[:id], name: resp[:name]) + steps = resp[:steps] + steps.each do |step| + workflow_step = Step.new(uuid: step[:uuid], + service_name: step[:serviceName], + workflow: workflow, + type_name: step[:stepConfiguration][:typeName], + previous_type_name: step[:stepConfiguration][:previousTypeName], + configuration_params: step[:stepConfiguration][:configurationParams]) + workflow.steps << workflow_step + end + workflow + end + + # Return the relevant step based on the given service name. + # For example, if you want the step related to the scan service you would pass 'nexpose-scan-service'. + # + # @param [String] service_name Service name to be returned. + # @return [Step] Step object corresponding to the given service. + # + def get_step(type_name) + @steps.find do |step| + step.type_name == type_name + end + end + + # Return the trigger step of a workflow. The trigger step is defined as a step that monitors for events + # that will cause the action to fire. + # + # Currently triggers do not have a previous-action so that is what this is returning. This behavior could change in ESO's future. + # + # @return [Step] Step object representation of the trigger step. + # + def trigger + @steps.find do |step| + step.stepConfiguration.previousTypeName.nil? + end + end + + # Return this object and the associated steps in a digestible JSON format. + # + # @return [String] JSON interpretation of this workflow. + # + def to_json + hash = self.to_hash + steps = hash["steps"] + hashified_steps = [] + steps.each {|step| hashified_steps << step.to_hash} + hash["steps"] = hashified_steps + hash.to_json + end + + # Return this object as a hash. + # The corresponding steps will still be objects. + # + # @return [Hash{}] Hash interpretation of this workflow. + def to_hash + hash = {} + instance_variables.each {|var| hash[var.to_s.delete("@")] = instance_variable_get(var)} + hash + end + + # Representation of state of a workflow or integration option. Taken from service-orchestration State.java + class State + # Workflow or an integration option is configured and ready to accept events + READY = 'ready' + + # Workflow or an integration option is processing or has processed events + RUNNING = 'running' + + # The workflow or an integration option is running, but is temporarily unsuccessful processing events + RETRY = 'retry' + + # Workflow or an integration option is stopped by the user + STOPPED = 'stopped' + + # Workflow or an integration option has experienced an error that caused it to stop + ERROR = 'error' + end + + class StateHistory < Struct.new(:message, :state, :startTime) + end + + class History < Workflow + # The current state of the workflow + attr_accessor :state + + # The most recent message + attr_accessor :message + + # An array of Eso::Workflow::StateHistory + attr_accessor :state_histories + + # Constructor for the WorkflowHistory + # + # @param [String] id ID of the workflow. + # @param [String] name Name of the workflow. + # @param [Array] steps Array of the steps that this workflow takes. + # @param [Fixnum] timeCreated The time the workflow was created in millis since epoch + # @param [Eso::Workflow::State] state The current state of the workflow + # @param [String] message The most recent message + def initialize (id:, name:, timeCreated:, steps:, state:, message:, history:) + super(id: id, name: name, timeCreated: timeCreated, steps: steps) + @state = state + @message = message + @state_histories = history + end + end + end +end From e87cb24a6b9c12be738630b1383dc14b06cb30b4 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Wed, 6 Dec 2017 16:34:00 -0600 Subject: [PATCH 05/58] NEX-50812: Add X-Requested-With header to eso and nexpose --- lib/eso/service.rb | 3 ++- lib/nexpose/ajax.rb | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/eso/service.rb b/lib/eso/service.rb index ae9d36ce..59b25254 100644 --- a/lib/eso/service.rb +++ b/lib/eso/service.rb @@ -58,6 +58,7 @@ def https(timeout:) def add_nexpose_session(request:) request.add_field('nexposeCCSessionID', @nexpose_console.session_id) request.add_field('Cookie', "nexposeCCSessionID=#{@nexpose_console.session_id}") + request.add_field('X-Requested-With', 'XMLHttpRequest') end def request(request:, timeout: nil) @@ -79,4 +80,4 @@ def request(request:, timeout: nil) end end end -end \ No newline at end of file +end diff --git a/lib/nexpose/ajax.rb b/lib/nexpose/ajax.rb index 9660a869..493fbc93 100644 --- a/lib/nexpose/ajax.rb +++ b/lib/nexpose/ajax.rb @@ -149,6 +149,7 @@ def https(nsc, timeout = nil) def headers(nsc, request) request.add_field('nexposeCCSessionID', nsc.session_id) request.add_field('Cookie', "nexposeCCSessionID=#{nsc.session_id}") + request.add_field('X-Requested-With', 'XMLHttpRequest') end def request(nsc, request, timeout = nil) From ae66880b7888f3d87999b18cbf6b4b1e6d69a8ed Mon Sep 17 00:00:00 2001 From: Sam Morris Date: Thu, 14 Dec 2017 16:06:25 -0600 Subject: [PATCH 06/58] store Array properties differently --- lib/eso/configuration/configuration.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/eso/configuration/configuration.rb b/lib/eso/configuration/configuration.rb index ccdd82f3..889afcb2 100644 --- a/lib/eso/configuration/configuration.rb +++ b/lib/eso/configuration/configuration.rb @@ -97,7 +97,12 @@ def to_hash def self.load(array) property = array.first value_class = array.last['valueClass'] - value = array.last['value'] + value = + if value_class == 'Array' + array.last['items'].map{|item| item['value']} + else + array.last['value'] + end self.new(property, value_class, value) end end From 534d2bd6e6f51a5b83abf21996666dac08b6d9b0 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Thu, 14 Dec 2017 21:57:42 -0600 Subject: [PATCH 07/58] Appease most of the houndci-bot complaints --- lib/eso/workflow.rb | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/lib/eso/workflow.rb b/lib/eso/workflow.rb index bdcd1b40..012835af 100644 --- a/lib/eso/workflow.rb +++ b/lib/eso/workflow.rb @@ -15,19 +15,18 @@ class Workflow # The time the workflow was created in milliseconds since epoch attr_accessor :timeCreated - # Constructor for the workflow # # @param [String] id ID of the workflow. # @param [String] name Name of the workflow. # @param [Array] steps Array of the steps that this workflow takes. - # @param [Fixnum] timeCreated The time the workflow was created in millis since epoch + # @param [Fixnum] time_created The time the workflow was created in millis since epoch # - def initialize(id: nil, name:, steps: [], timeCreated: (Time.now.strftime('%s').to_i * 1000) ) + def initialize(id: nil, name:, steps: [], time_created: (Time.now.strftime('%s').to_i * 1000)) @id = id @name = name @steps = steps - @timeCreated = timeCreated + @timeCreated = time_created end # Load an existing workflow from the API. @@ -84,10 +83,10 @@ def trigger # def to_json hash = self.to_hash - steps = hash["steps"] + steps = hash['steps'] hashified_steps = [] - steps.each {|step| hashified_steps << step.to_hash} - hash["steps"] = hashified_steps + steps.each { |step| hashified_steps << step.to_hash } + hash['steps'] = hashified_steps hash.to_json end @@ -97,12 +96,12 @@ def to_json # @return [Hash{}] Hash interpretation of this workflow. def to_hash hash = {} - instance_variables.each {|var| hash[var.to_s.delete("@")] = instance_variable_get(var)} + instance_variables.each { |var| hash[var.to_s.delete('@')] = instance_variable_get(var) } hash end # Representation of state of a workflow or integration option. Taken from service-orchestration State.java - class State + module State # Workflow or an integration option is configured and ready to accept events READY = 'ready' @@ -119,8 +118,7 @@ class State ERROR = 'error' end - class StateHistory < Struct.new(:message, :state, :startTime) - end + StateHistory = Struct.new(:message, :state, :startTime) class History < Workflow # The current state of the workflow @@ -137,11 +135,11 @@ class History < Workflow # @param [String] id ID of the workflow. # @param [String] name Name of the workflow. # @param [Array] steps Array of the steps that this workflow takes. - # @param [Fixnum] timeCreated The time the workflow was created in millis since epoch + # @param [Fixnum] time_created The time the workflow was created in millis since epoch # @param [Eso::Workflow::State] state The current state of the workflow # @param [String] message The most recent message - def initialize (id:, name:, timeCreated:, steps:, state:, message:, history:) - super(id: id, name: name, timeCreated: timeCreated, steps: steps) + def initialize(id:, name:, time_created:, steps:, state:, message:, history:) + super(id: id, name: name, timeCreated: time_created, steps: steps) @state = state @message = message @state_histories = history From 8ca5878a7e64e75eb2903a293ea130f195f88696 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Fri, 15 Dec 2017 19:01:27 -0600 Subject: [PATCH 08/58] Remove eso version file --- lib/eso.rb | 1 - lib/eso/version.rb | 3 --- 2 files changed, 4 deletions(-) delete mode 100644 lib/eso/version.rb diff --git a/lib/eso.rb b/lib/eso.rb index dd1933e0..4d1d5120 100644 --- a/lib/eso.rb +++ b/lib/eso.rb @@ -16,7 +16,6 @@ require 'eso/service' require 'eso/step' require 'eso/step_configuration' -require 'eso/version' require 'eso/workflow' module Eso diff --git a/lib/eso/version.rb b/lib/eso/version.rb deleted file mode 100644 index edbef1dd..00000000 --- a/lib/eso/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Eso - VERSION = '2.2.1' -end From bf59a32dc4398a296a8f83e734349ac777b91b69 Mon Sep 17 00:00:00 2001 From: Sam Morris Date: Mon, 18 Dec 2017 13:16:07 -0600 Subject: [PATCH 09/58] add nil guard in property method --- lib/eso/configuration/configuration.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/eso/configuration/configuration.rb b/lib/eso/configuration/configuration.rb index 889afcb2..c841c4c9 100644 --- a/lib/eso/configuration/configuration.rb +++ b/lib/eso/configuration/configuration.rb @@ -36,7 +36,8 @@ def to_hash # @param [String] name The name of the property to retrieve # @return [String] The value of the property def property(name) - properties.find{|attr| attr.property == name}.value + prop = properties.find{|attr| attr.property == name} + prop.value unless prop.nil? end # Update a Configuration attribute property value given the name of the property From b6734b6390464512ae97040be69fb222f24b3875 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Mon, 8 Jan 2018 16:49:28 -0800 Subject: [PATCH 10/58] Update copyright year and add install instruction to readme --- COPYING | 2 +- README.markdown | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/COPYING b/COPYING index 1ce315d8..314de5be 100644 --- a/COPYING +++ b/COPYING @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2014-2017, Rapid7, Inc. +Copyright (c) 2014-2018, Rapid7, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.markdown b/README.markdown index fb39589f..47cf6414 100644 --- a/README.markdown +++ b/README.markdown @@ -11,6 +11,8 @@ This gem is heavily used for internal, automated testing of the Nexpose product. Since version 1.0 nexpose-client uses [Semantic Versioning](http://semver.org/). This allows for confident use of the [pessimistic operator](https://robots.thoughtbot.com/rubys-pessimistic-operator) in scripts or larger ruby projects. +Install the gem with Rubygems: `gem install nexpose` + ## Release Notes Release notes are available on the [Releases](https://github.com/rapid7/nexpose-client/releases) page. From 898681ad030658f6397bc5b1f9380d94f0125fad Mon Sep 17 00:00:00 2001 From: Michael Huffman Date: Wed, 17 Jan 2018 08:04:32 -0800 Subject: [PATCH 11/58] Update vuln exceptions to use generally available API version --- lib/nexpose/vuln_exception.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nexpose/vuln_exception.rb b/lib/nexpose/vuln_exception.rb index fe9655ad..f164ee45 100644 --- a/lib/nexpose/vuln_exception.rb +++ b/lib/nexpose/vuln_exception.rb @@ -22,14 +22,14 @@ def list_vuln_exceptions(status = nil) url_size = 500 url_page = 0 - req = Nexpose::AJAX.get(self, "/api/experimental/vulnerability_exceptions?_size=#{url_size}&_page=#{url_page}") + req = Nexpose::AJAX.get(self, "/api/3/vulnerability_exceptions?size=#{url_size}&page=#{url_page}") data = JSON.parse(req, object_class: OpenStruct) ajax_data << data._resources if data._links.count > 1 loop do url_page += 1 - req = Nexpose::AJAX.get(self, "/api/experimental/vulnerability_exceptions?_size=#{url_size}&_page=#{url_page}") + req = Nexpose::AJAX.get(self, "/api/3/vulnerability_exceptions?size=#{url_size}&page=#{url_page}") data = JSON.parse(req, object_class: OpenStruct) ajax_data << data._resources links = data._links.select { |ll| ['self', 'last'].include?(ll.rel) } From d629ca75f64cda00861e64f690b795447d4a3517 Mon Sep 17 00:00:00 2001 From: Michael Huffman Date: Wed, 17 Jan 2018 08:31:32 -0800 Subject: [PATCH 12/58] Fix reference to "links" property --- lib/nexpose/vuln_exception.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nexpose/vuln_exception.rb b/lib/nexpose/vuln_exception.rb index f164ee45..35dbf42b 100644 --- a/lib/nexpose/vuln_exception.rb +++ b/lib/nexpose/vuln_exception.rb @@ -26,13 +26,13 @@ def list_vuln_exceptions(status = nil) data = JSON.parse(req, object_class: OpenStruct) ajax_data << data._resources - if data._links.count > 1 + if data.links.count > 1 loop do url_page += 1 req = Nexpose::AJAX.get(self, "/api/3/vulnerability_exceptions?size=#{url_size}&page=#{url_page}") data = JSON.parse(req, object_class: OpenStruct) ajax_data << data._resources - links = data._links.select { |ll| ['self', 'last'].include?(ll.rel) } + links = data.links.select { |ll| ['self', 'last'].include?(ll.rel) } break if links[0].href == links[1].href end end From 6171d9408b363d6c8290a95c1d977273bc3cf7c8 Mon Sep 17 00:00:00 2001 From: Michael Huffman Date: Wed, 17 Jan 2018 08:41:27 -0800 Subject: [PATCH 13/58] Fix reference to "resources" --- lib/nexpose/vuln_exception.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nexpose/vuln_exception.rb b/lib/nexpose/vuln_exception.rb index 35dbf42b..1cccd1c7 100644 --- a/lib/nexpose/vuln_exception.rb +++ b/lib/nexpose/vuln_exception.rb @@ -24,14 +24,14 @@ def list_vuln_exceptions(status = nil) req = Nexpose::AJAX.get(self, "/api/3/vulnerability_exceptions?size=#{url_size}&page=#{url_page}") data = JSON.parse(req, object_class: OpenStruct) - ajax_data << data._resources + ajax_data << data.resources if data.links.count > 1 loop do url_page += 1 req = Nexpose::AJAX.get(self, "/api/3/vulnerability_exceptions?size=#{url_size}&page=#{url_page}") data = JSON.parse(req, object_class: OpenStruct) - ajax_data << data._resources + ajax_data << data.resources links = data.links.select { |ll| ['self', 'last'].include?(ll.rel) } break if links[0].href == links[1].href end From a4baf5df559aeb2d4c922603336d6b322edd0afc Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Wed, 17 Jan 2018 12:35:47 -0800 Subject: [PATCH 14/58] Bump version for release [skip ci] --- lib/nexpose/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nexpose/version.rb b/lib/nexpose/version.rb index 490b8733..e6f531d8 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.1.2'.freeze + VERSION = '7.2.0'.freeze end From 24c17867b444fbd240f6b1f8d722d4aed5ad9d77 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Wed, 17 Jan 2018 12:40:30 -0800 Subject: [PATCH 15/58] Update changelog [skip ci] --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index defdc5ba..94a9317d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Change Log +## [v7.2.0](https://github.com/rapid7/nexpose-client/tree/v7.2.0) (2018-01-17) +[Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.1.1...v7.2.0) + +**Closed issues:** + +- list\_vuln\_exceptions returns API error [\#312](https://github.com/rapid7/nexpose-client/issues/312) +- Credentials failure after using Site.copy [\#307](https://github.com/rapid7/nexpose-client/issues/307) +- XML serialization for VulnException incorrect due to extra whitespace [\#304](https://github.com/rapid7/nexpose-client/issues/304) +- Nexpose timeout does not seem to work [\#299](https://github.com/rapid7/nexpose-client/issues/299) + +**Merged pull requests:** + +- Update vuln exceptions to use generally available API version [\#313](https://github.com/rapid7/nexpose-client/pull/313) ([mhuffman-r7](https://github.com/mhuffman-r7)) +- Add a method to add common vuln status filters to report configs [\#303](https://github.com/rapid7/nexpose-client/pull/303) ([gschneider-r7](https://github.com/gschneider-r7)) +- Updated for Ruby 2.4 Support [\#301](https://github.com/rapid7/nexpose-client/pull/301) ([twosevenzero](https://github.com/twosevenzero)) + ## [v7.1.1](https://github.com/rapid7/nexpose-client/tree/v7.1.1) (2017-09-28) [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.1.0...v7.1.1) From 2bdc3fef9ae998a957d0ea4bf77eed2d779290e2 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Thu, 18 Jan 2018 16:45:16 -0600 Subject: [PATCH 16/58] Enhanced AWSv2 ARN messages --- lib/eso/configuration/configuration_manager.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/eso/configuration/configuration_manager.rb b/lib/eso/configuration/configuration_manager.rb index 190cf36c..fc1d87fd 100644 --- a/lib/eso/configuration/configuration_manager.rb +++ b/lib/eso/configuration/configuration_manager.rb @@ -125,6 +125,11 @@ def preview_assets(configuration) module ConfigManagerMessages module TestConfig + AUTH_FAILED_AWS = 'Could not authenticate to Amazon Web Services.' + + # Actual message will list out the bad ARNs + AUTH_FAILED_AWS_ARN = /Could not authenticate to Amazon Web Services with the following ARNs/ + CONNECTION_SUCCESSFUL = 'The connection to the external service was successful.' # Applies to invalid user, password, wrong protocol, can't reach server, bad base or search query From 116a77f1ae42341e4052e9d6e634b8800e53c777 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Tue, 30 Jan 2018 15:12:29 -0600 Subject: [PATCH 17/58] Document more Error messages returned by the ConfigManager --- lib/eso/configuration/configuration_manager.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/eso/configuration/configuration_manager.rb b/lib/eso/configuration/configuration_manager.rb index fc1d87fd..dcfdd3d0 100644 --- a/lib/eso/configuration/configuration_manager.rb +++ b/lib/eso/configuration/configuration_manager.rb @@ -125,17 +125,21 @@ def preview_assets(configuration) module ConfigManagerMessages module TestConfig - AUTH_FAILED_AWS = 'Could not authenticate to Amazon Web Services.' - + AUTH_FAILED_AWS = 'Could not authenticate to Amazon Web Services.' # Actual message will list out the bad ARNs - AUTH_FAILED_AWS_ARN = /Could not authenticate to Amazon Web Services with the following ARNs/ + AUTH_FAILED_AWS_ARN = /Could not authenticate to Amazon Web Services with the following ARNs/ CONNECTION_SUCCESSFUL = 'The connection to the external service was successful.' - # Applies to invalid user, password, wrong protocol, can't reach server, bad base or search query - CONNECTION_FAILED = 'The connection to the external service failed.' + CONNECTION_FAILED = 'The connection to the external service failed.' + + INVALID_FIELDS = 'The configuration had invalid fields.' - INVALID_FIELDS = 'The configuration had invalid fields.' + RETRY_AD = 'Failed to reach out to the Active Directory service, will try again.' + RETRY_AWS = 'Failed to reach out to Amazon Web Services, will try again.' + RETRY_AZURE = 'Failed to reach out to the Azure service, will try again.' + RETRY_DXL = 'The DXL connection is currently down and the connection is in retry status.' + RETRY_EPO = 'Failed to reach out to the ePO service, will try again.' end end end From 74e5564dcc2cece4313ad5da534a9002fc02bea8 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Mon, 9 Apr 2018 18:16:27 -0700 Subject: [PATCH 18/58] Remove ruby-head from travis-ci Something isn't working on the travis-ci side, so just drop it for now to stop failing builds on an otherwise perfectly working gem. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e124fdf2..ceca0d2a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ rvm: - 2.2.6 - 2.3.3 - 2.4.0 - - ruby-head - jruby-9.0.5.0 jdk: - oraclejdk8 From 9ff95f244a84784b1be7edbf8599f93378975249 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 1 Jun 2018 11:49:28 -0500 Subject: [PATCH 19/58] When passed a filename, download a report in chunks Rather than pulling an entire 6-8 GB report into a string in memory to immediately write it out to a file, use the built-in feature of Net::HTTP to retrieve the result in chunks and write them out as they are read from the remote host. This prevents receiving `NoMemoryError` issues when downloading huge reports. --- lib/nexpose/connection.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/nexpose/connection.rb b/lib/nexpose/connection.rb index e262a691..afcc84f9 100644 --- a/lib/nexpose/connection.rb +++ b/lib/nexpose/connection.rb @@ -143,11 +143,15 @@ def download(url, file_name = nil) http.cert_store = @trust_store end headers = { 'Cookie' => "nexposeCCSessionID=#{@session_id}" } - resp = http.get(uri.to_s, headers) if file_name - ::File.open(file_name, 'wb') { |file| file.write(resp.body) } + http.request_get(uri.to_s, headers) do |resp| + ::File.open(file_name, 'wb') do |file| + resp.read_body { |chunk| file.write(chunk) } + end + end else + resp = http.get(uri.to_s, headers) resp.body end end From 9d3526431fac646ed6c638b1b3ebc59c133b5e03 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 1 Jun 2018 11:53:22 -0500 Subject: [PATCH 20/58] Bump to latest ruby minor releases and add 2.5.x to the builds Ruby 2.5 has been out for some time now, we should make sure tests work. --- .travis.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index ceca0d2a..eec5076d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,11 @@ language: ruby sudo: false cache: bundler rvm: - - 2.1.9 - - 2.2.6 - - 2.3.3 - - 2.4.0 + - 2.1.10 + - 2.2.10 + - 2.3.7 + - 2.4.4 + - 2.5.1 - jruby-9.0.5.0 jdk: - oraclejdk8 From 74b4b3f762dd7a5e8b3e278dd02a67dc90fe97f9 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 1 Jun 2018 12:39:43 -0500 Subject: [PATCH 21/58] Add tests for connection.download method This adds three different tests for three different ways to call this method. --- spec/fixtures/cassettes/download_report.yml | 95 +++++++++++++++++++++ spec/nexpose/connection/download_spec.rb | 48 +++++++++++ 2 files changed, 143 insertions(+) create mode 100644 spec/fixtures/cassettes/download_report.yml create mode 100644 spec/nexpose/connection/download_spec.rb diff --git a/spec/fixtures/cassettes/download_report.yml b/spec/fixtures/cassettes/download_report.yml new file mode 100644 index 00000000..cca0bd5a --- /dev/null +++ b/spec/fixtures/cassettes/download_report.yml @@ -0,0 +1,95 @@ +--- +http_interactions: +- request: + method: post + uri: https://nexpose.local:3780/api/1.1/xml + body: + encoding: UTF-8 + string: "" + headers: + Content-Type: + - text/xml + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + X-Frame-Options: + - SAMEORIGIN + X-Ua-Compatible: + - IE=edge,chrome=1 + Set-Cookie: + - JSESSIONID=6D064F67374C1663E32D088987E90ED5; Path=/; Secure; HttpOnly + Date: + - Fri, 27 Mar 2015 19:44:40 GMT + Server: + - NSC/0.6.4 (JVM) + Cache-Control: + - no-cache; max-age=0 + Pragma: + - no-cache + Content-Type: + - application/xml;charset=UTF-8 + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + body: + encoding: ASCII-8BIT + string: | + + http_version: + recorded_at: Fri, 27 Mar 2015 19:44:40 GMT +- request: + method: get + uri: https://nexpose.local:3780/reports/00000001/00000002/report.xml + body: + encoding: US-ASCII + string: '' + headers: + Cookie: + - nexposeCCSessionID=XXX + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + X-Frame-Options: + - SAMEORIGIN + X-Ua-Compatible: + - IE=edge,chrome=1 + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + Cache-Control: + - no-store, must-revalidate + Content-Disposition: + - filename=report.xml + Content-Type: + - application/xml;charset=UTF-8 + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Date: + - Thu, 25 Aug 2016 15:37:38 GMT + Server: + - Security Console + body: + encoding: ASCII-8BIT + string: "" + http_version: + recorded_at: Thu, 25 Aug 2016 15:37:39 GMT diff --git a/spec/nexpose/connection/download_spec.rb b/spec/nexpose/connection/download_spec.rb new file mode 100644 index 00000000..1f452534 --- /dev/null +++ b/spec/nexpose/connection/download_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' +require 'tempfile' + +describe Nexpose::Connection, :with_api_login do + describe '#download' do + let(:report_url) { 'https://nexpose.local:3780/reports/00000001/00000002/report.xml' } + + it 'downloads report to string' do + report = VCR.use_cassette('download_report') do + connection.download(report_url) + end + + expect(report).to eq('') + end + + it 'downloads report with file name' do + tf = Tempfile.new + path = tf.path + tf.close + tf.unlink + + begin + VCR.use_cassette('download_report') do + connection.download(report_url, path) + end + + expect(File.read(path)).to eq('') + ensure + File.delete(path) if File.exist?(path) + end + end + + it 'downloads report with file object' do + tf = Tempfile.new + + begin + VCR.use_cassette('download_report') do + connection.download(report_url, tf) + end + + expect(tf.read).to eq('') + ensure + tf.close + tf.unlink + end + end + end +end From f366367ee4706c61283593f6f9a9715974a24777 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 1 Jun 2018 14:19:54 -0500 Subject: [PATCH 22/58] Include basename in Tempfile.new to be 2.1 compatible --- spec/nexpose/connection/download_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/nexpose/connection/download_spec.rb b/spec/nexpose/connection/download_spec.rb index 1f452534..fb6b34d0 100644 --- a/spec/nexpose/connection/download_spec.rb +++ b/spec/nexpose/connection/download_spec.rb @@ -14,7 +14,7 @@ end it 'downloads report with file name' do - tf = Tempfile.new + tf = Tempfile.new('download_spec') path = tf.path tf.close tf.unlink @@ -31,7 +31,7 @@ end it 'downloads report with file object' do - tf = Tempfile.new + tf = Tempfile.new('download_spec') begin VCR.use_cassette('download_report') do From 803795a8bb1dfb2219dba406c198c523f9d993a0 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Fri, 1 Jun 2018 16:35:34 -0700 Subject: [PATCH 23/58] Fix license reference in gemspec --- nexpose.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nexpose.gemspec b/nexpose.gemspec index 6853029b..6286ca87 100644 --- a/nexpose.gemspec +++ b/nexpose.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.homepage = 'https://github.com/rapid7/nexpose-client' s.summary = 'Ruby API for Rapid7 Nexpose' s.description = 'This gem provides a Ruby API to the Nexpose vulnerability management product by Rapid7.' - s.license = 'BSD' + s.license = 'BSD-3-Clause' s.authors = ['HD Moore', 'Chris Lee', 'Michael Daines', 'Brandon Turner', 'Gavin Schneider', 'Scott Green'] s.email = ['hd_moore@rapid7.com', 'christopher_lee@rapid7.com', 'michael_daines@rapid7.com', 'brandon_turner@rapid7.com', 'gavin_schneider@rapid7.com', 'scott_green@rapid7.com'] s.files = Dir['[A-Z]*'] + Dir['lib/**/*'] From 68180f3ecad4746890bfbd04fd744fe27022d962 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Fri, 1 Jun 2018 16:36:27 -0700 Subject: [PATCH 24/58] Bump version for release --- lib/nexpose/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nexpose/version.rb b/lib/nexpose/version.rb index e6f531d8..8fcfa6e2 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.2.0'.freeze + VERSION = '7.2.1'.freeze end From e9727ad533b079679d25491b62c4ad8e0b254a1a Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Fri, 1 Jun 2018 16:45:36 -0700 Subject: [PATCH 25/58] Update changelog [skip ci] --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94a9317d..d02038bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Change Log +## [v7.2.1](https://github.com/rapid7/nexpose-client/tree/v7.2.1) (2018-06-01) +[Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.2.0...v7.2.1) + +**Closed issues:** + +- api/3/assets/{id}/software returns HTTP.500 error [\#319](https://github.com/rapid7/nexpose-client/issues/319) +- Unknown SSH Handshake error [\#308](https://github.com/rapid7/nexpose-client/issues/308) +- Use rex-mime gem instead of bundled "rexlite/mime" dependency [\#253](https://github.com/rapid7/nexpose-client/issues/253) + +**Merged pull requests:** + +- When passed a filename, download a report in chunks [\#321](https://github.com/rapid7/nexpose-client/pull/321) ([toofishes](https://github.com/toofishes)) + ## [v7.2.0](https://github.com/rapid7/nexpose-client/tree/v7.2.0) (2018-01-17) [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.1.1...v7.2.0) From 933fc8c0c85ba11d3e17db1d7f4542816f400d71 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Wed, 6 Jun 2018 16:44:09 -0700 Subject: [PATCH 26/58] Add deprecated notice to readme --- README.markdown | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 47cf6414..27954230 100644 --- a/README.markdown +++ b/README.markdown @@ -1,5 +1,10 @@ +# DEPRECATED +The [RESTful API for the Nexpose/InsightVM Security Console](https://help.rapid7.com/insightvm/en-us/api/index.html) has rendered this library obsolete. If you require a Ruby library for that API you can use a [generated client](https://github.com/rapid7/vm-console-client-ruby). Clients for other languages can be generated from the Swagger specification. Note that generated clients are not officially supported or maintained by Rapid7. + +While this project is no longer under active development, it is still maintained by Rapid7 for internal testing needs. Pull requests will continue to be reviewed and accepted, and new versions published as requested. + # Nexpose-Client -[![Gem Version](https://badge.fury.io/rb/nexpose.svg)](http://badge.fury.io/rb/nexpose) [![Build Status](https://travis-ci.org/rapid7/nexpose-client.svg?branch=master)](https://travis-ci.org/rapid7/nexpose-client) [![Test Coverage](https://codeclimate.com/github/rapid7/nexpose-client/badges/coverage.svg)](https://codeclimate.com/github/rapid7/nexpose-client) [![Inline docs](http://inch-ci.org/github/rapid7/nexpose-client.svg?branch=master)](http://inch-ci.org/github/rapid7/nexpose-client) [![Code Climate](https://codeclimate.com/github/rapid7/nexpose-client/badges/gpa.svg)](https://codeclimate.com/github/rapid7/nexpose-client) +[![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) [![Gem Version](https://badge.fury.io/rb/nexpose.svg)](http://badge.fury.io/rb/nexpose) [![Build Status](https://travis-ci.org/rapid7/nexpose-client.svg?branch=master)](https://travis-ci.org/rapid7/nexpose-client) [![Test Coverage](https://codeclimate.com/github/rapid7/nexpose-client/badges/coverage.svg)](https://codeclimate.com/github/rapid7/nexpose-client) [![Inline docs](http://inch-ci.org/github/rapid7/nexpose-client.svg?branch=master)](http://inch-ci.org/github/rapid7/nexpose-client) [![Code Climate](https://codeclimate.com/github/rapid7/nexpose-client/badges/gpa.svg)](https://codeclimate.com/github/rapid7/nexpose-client) This is the official gem package for the Ruby Nexpose API client library. From e044c54a9cd212dbcdb7f3f9b3445f05d60332f7 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Fri, 13 Jul 2018 02:47:24 -0500 Subject: [PATCH 27/58] QE-XXXX: Required fixes for AWS configs w/ array props --- lib/eso/configuration/configuration.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/eso/configuration/configuration.rb b/lib/eso/configuration/configuration.rb index c841c4c9..9896430b 100644 --- a/lib/eso/configuration/configuration.rb +++ b/lib/eso/configuration/configuration.rb @@ -25,7 +25,7 @@ def to_hash hash = {:configId => @config_id, :serviceName => @service_name, :configName => @config_name, - :configurationAttributes => {:valueClass => 'Object', + :configurationAttributes => {:valueClass => Eso::Values::OBJECT, :objectType => 'service_configuration', :properties => []}} properties.each {|prop| hash[:configurationAttributes][:properties] << prop.to_hash} @@ -88,7 +88,14 @@ def to_hash prop = @property.to_sym hash = {prop => {}} hash[prop]['valueClass'] = @value_class - hash[prop]['value'] = @value + if @value_class == Eso::Values::ARRAY + items = [] + @value.each{|v| items<< {'value' => v, 'valueClass' => Eso::Values::STRING}} + hash[prop]['items'] = items + else + hash[prop]['value'] = @value + end + hash end # Load a ConfigurationAttribute object from an Array @@ -99,7 +106,7 @@ def self.load(array) property = array.first value_class = array.last['valueClass'] value = - if value_class == 'Array' + if value_class == Eso::Values::ARRAY array.last['items'].map{|item| item['value']} else array.last['value'] From ef65ef083d31d101db653d2416a738e7094a1717 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Wed, 18 Jul 2018 12:07:05 -0500 Subject: [PATCH 28/58] QE-XXXX: Add ability to delete a property on a Configuration --- lib/eso/configuration/configuration.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/eso/configuration/configuration.rb b/lib/eso/configuration/configuration.rb index 9896430b..f3e57b76 100644 --- a/lib/eso/configuration/configuration.rb +++ b/lib/eso/configuration/configuration.rb @@ -49,6 +49,13 @@ def update_property(name, value) properties.find{|attr| attr.property == name}.value = value end + # Delete a Configuration attribute property value given the name of the property + # + # @param [String] name The name of the property to update + def delete_property(name) + properties.delete_if{|attr| attr.property == name} + end + # Load a Configuration object from a Hash # # @param [Hash] hash The Hash containing the Configuration object From 381d054a7c09911e718dee145bbf3ba86576d1b3 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Fri, 27 Jul 2018 23:04:46 -0500 Subject: [PATCH 29/58] Adds support for AWS asset+tag sync --- lib/eso/integration_options_manager.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/eso/integration_options_manager.rb b/lib/eso/integration_options_manager.rb index eb0a3f37..ee6067b2 100644 --- a/lib/eso/integration_options_manager.rb +++ b/lib/eso/integration_options_manager.rb @@ -114,6 +114,19 @@ def self.build_sync_azure_assets_option(name:, discovery_conn_id:, site_id: nil) IntegrationOption.new(name: name, steps: [step1, step2]) end + def self.build_sync_aws_assets_with_tags_option(name:, discovery_conn_id:, site_id: nil, tags: '') + step1 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::DISCOVER_AWS_ASSETS) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + .add_property(StepConfiguration::ConfigParamProperties::IMPORT_TAGS, true) + .add_property(StepConfiguration::ConfigParamProperties::EXCLUDE_ASSETS_WITH_TAGS, "") + .add_property(StepConfiguration::ConfigParamProperties::ONLY_IMPORT_THESE_TAGS, tags) + step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::SYNC_EXTERNAL, previous_type_name: step1.type_name) + + #This isn't always known immediately, which is why we have IntegrationOption.site_id= + step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id + IntegrationOption.new(name: name, steps: [step1, step2]) + end + def self.build_sync_azure_assets_with_tags_option(name:, discovery_conn_id:, site_id: nil, tags: '') step1 = Step.new(service_name: ServiceNames::AZURE, type_name: StepNames::DISCOVER_AZURE_ASSETS) .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) From cc1e8a7f880a5e21c2c8b696ddd08d85a6d3466d Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Wed, 8 Aug 2018 16:13:54 -0500 Subject: [PATCH 30/58] QE-587: Add verify-aws-target Int Option support ...and continue to feel the pain of creating more build_* methods when I really want to refactor this whole thing --- lib/eso/integration_options_manager.rb | 16 +++++++++++++--- lib/eso/nexpose.rb | 3 +++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/eso/integration_options_manager.rb b/lib/eso/integration_options_manager.rb index ee6067b2..524ea8c8 100644 --- a/lib/eso/integration_options_manager.rb +++ b/lib/eso/integration_options_manager.rb @@ -104,6 +104,16 @@ def self.build_sync_aws_assets_option(name:, discovery_conn_id:, site_id: nil) IntegrationOption.new(name: name, steps: [step1, step2]) end + def self.build_verify_aws_targets_option(name:, discovery_conn_id:) + step1 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::VERIFY_AWS_ASSETS) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::VERIFY_EXTERNAL_TARGETS, previous_type_name: step1.type_name) + step3 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::VERIFY_AWS_ASSETS) + .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) + + IntegrationOption.new(name: name, steps: [step1, step2, step3]) + end + def self.build_sync_azure_assets_option(name:, discovery_conn_id:, site_id: nil) step1 = Step.new(service_name: ServiceNames::AZURE, type_name: StepNames::DISCOVER_AZURE_ASSETS) .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) @@ -127,12 +137,12 @@ def self.build_sync_aws_assets_with_tags_option(name:, discovery_conn_id:, site_ IntegrationOption.new(name: name, steps: [step1, step2]) end - def self.build_sync_azure_assets_with_tags_option(name:, discovery_conn_id:, site_id: nil, tags: '') + def self.build_sync_azure_assets_with_tags_option(name:, discovery_conn_id:, site_id: nil, only_tags: '', exclude_tags: '') step1 = Step.new(service_name: ServiceNames::AZURE, type_name: StepNames::DISCOVER_AZURE_ASSETS) .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) .add_property(StepConfiguration::ConfigParamProperties::IMPORT_TAGS, true) - .add_property(StepConfiguration::ConfigParamProperties::EXCLUDE_ASSETS_WITH_TAGS, "") - .add_property(StepConfiguration::ConfigParamProperties::ONLY_IMPORT_THESE_TAGS, tags) + .add_property(StepConfiguration::ConfigParamProperties::EXCLUDE_ASSETS_WITH_TAGS, exclude_tags) + .add_property(StepConfiguration::ConfigParamProperties::ONLY_IMPORT_THESE_TAGS, only_tags) step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::SYNC_EXTERNAL, previous_type_name: step1.type_name) #This isn't always known immediately, which is why we have IntegrationOption.site_id= diff --git a/lib/eso/nexpose.rb b/lib/eso/nexpose.rb index e151790c..37d37819 100644 --- a/lib/eso/nexpose.rb +++ b/lib/eso/nexpose.rb @@ -32,6 +32,8 @@ module StepNames SCAN_IN_SITE = 'scan-in-site' SYNC_EXTERNAL = 'sync-external-assets' TAG = 'tag' + VERIFY_AWS_ASSETS = 'verify-aws-targets' + VERIFY_EXTERNAL_TARGETS = 'verify-external-targets' VULN_DETAILS = 'vulnerability-details' VULN_DETAILS_REQUEST = 'vulnerability-details-request' end @@ -66,6 +68,7 @@ module StepConfigTypes StepNames::SCAN_IN_SITE, StepNames::SYNC_EXTERNAL] TAG = [StepNames::TAG] + VERIFY = [StepNames::DISCOVER_AWS_ASSETS] end module Filters From b67818715492c9dad9980bda096c6dcf4b49e982 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Thu, 9 Aug 2018 12:15:37 -0500 Subject: [PATCH 31/58] QE-587: Missed a previous_type_name for verify_aws_targets --- lib/eso/integration_options_manager.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/eso/integration_options_manager.rb b/lib/eso/integration_options_manager.rb index 524ea8c8..83f8b1fd 100644 --- a/lib/eso/integration_options_manager.rb +++ b/lib/eso/integration_options_manager.rb @@ -107,8 +107,10 @@ def self.build_sync_aws_assets_option(name:, discovery_conn_id:, site_id: nil) def self.build_verify_aws_targets_option(name:, discovery_conn_id:) step1 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::VERIFY_AWS_ASSETS) .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) - step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::VERIFY_EXTERNAL_TARGETS, previous_type_name: step1.type_name) - step3 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::VERIFY_AWS_ASSETS) + step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::VERIFY_EXTERNAL_TARGETS, + previous_type_name: step1.type_name) + step3 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::VERIFY_AWS_ASSETS, + previous_type_name: step2.type_name) .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id) IntegrationOption.new(name: name, steps: [step1, step2, step3]) From 4425afff2cd65436e5bb45bc9a0a2760923070f9 Mon Sep 17 00:00:00 2001 From: Heather Wilson Date: Mon, 27 Aug 2018 18:23:38 -0500 Subject: [PATCH 32/58] Non-required change which makes the JSON for configs consistent --- lib/eso/step_configuration.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/eso/step_configuration.rb b/lib/eso/step_configuration.rb index 038ba4ff..6c51fb48 100644 --- a/lib/eso/step_configuration.rb +++ b/lib/eso/step_configuration.rb @@ -25,7 +25,7 @@ def initialize (typeName, previousTypeName, configurationParams=nil, workflowID= @previousTypeName = previousTypeName @configurationParams = configurationParams ? configurationParams : { :valueClass => Values::OBJECT, - :objectType => typeName, + :objectType => 'params', :properties => {}} @workflowID = workflowID if workflowID end From 83e8ab7c2b27e3e0d30bbe517690897896508f5f Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Mon, 10 Feb 2020 14:28:05 -0800 Subject: [PATCH 33/58] Fix travis builds (#326) * Update ruby versions, drop jruby * Remove before-install step * Allow 2.6.5 to fail for now --- .travis.yml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index eec5076d..bc616fdb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,14 +2,13 @@ language: ruby sudo: false cache: bundler rvm: - - 2.1.10 - - 2.2.10 - - 2.3.7 - - 2.4.4 - - 2.5.1 - - jruby-9.0.5.0 -jdk: - - oraclejdk8 + - 2.3.8 + - 2.4.9 + - 2.5.7 + - 2.6.5 +matrix: + allow_failures: + - rvm: 2.6.5 script: bundle exec rspec --color --format=documentation addons: code_climate: @@ -22,5 +21,3 @@ branches: only: - master - /^staging.*$/ -before_install: - - gem update --system From 6798f8c77d9c8f97a163a118ffec49f2e81bca62 Mon Sep 17 00:00:00 2001 From: Adam Bunn Date: Tue, 13 Oct 2020 20:36:57 -0400 Subject: [PATCH 34/58] Fix HostOrIP for Ruby 2.6.3 This addresses https://github.com/rapid7/nexpose-client/issues/325 --- lib/nexpose/util.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nexpose/util.rb b/lib/nexpose/util.rb index e8a3971f..2cbebdee 100644 --- a/lib/nexpose/util.rb +++ b/lib/nexpose/util.rb @@ -55,7 +55,7 @@ def convert(asset) IPAddr.new(ips[1]) if ips[1] IPRange.new(ips[0], ips[1]) rescue ArgumentError => e - if e.message == 'invalid address' + if e.message =~ /invalid address/ HostName.new(asset) else raise "Unable to parse asset: '#{asset}'. #{e.message}" From 84242251c83b9f8bae322a97aedace087f65f4fc Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Mon, 11 Jan 2021 13:55:44 -0600 Subject: [PATCH 35/58] Add a new privilege ManageAdvPolicies EA-6367 --- lib/nexpose/role.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nexpose/role.rb b/lib/nexpose/role.rb index 78ac1eac..4f2fb2c7 100644 --- a/lib/nexpose/role.rb +++ b/lib/nexpose/role.rb @@ -24,6 +24,7 @@ module Global ADD_USERS_TO_REPORT = 'AddUsersToReport' MANAGE_POLICIES = 'ManagePolicies' MANAGE_TAGS = 'ManageTags' + MANAGE_ADVPOLICIES = 'ManageAdvPolicies' end module Site From 1f950ebf6e06b1a64544888321b3cdb7f9b759e5 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Mon, 11 Jan 2021 16:19:05 -0600 Subject: [PATCH 36/58] create github actions file --- .github/workflows/ruby.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/ruby.yml diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml new file mode 100644 index 00000000..d2d4ed1a --- /dev/null +++ b/.github/workflows/ruby.yml @@ -0,0 +1,32 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake +# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby + +name: Ruby + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + test: + + runs-on: ubuntu-latest + strategy: + matrix: + ruby-version: ['2.5', '2.6', '2.7', '3.0'] + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - name: Run tests + run: bundle exec rake From 4caf1ca51ae909e9992f7202cf48cbc4f4254bc4 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Mon, 11 Jan 2021 16:46:05 -0600 Subject: [PATCH 37/58] update ruby workflow remove bundler version use rspec to run tests instead of rake --- .github/workflows/ruby.yml | 2 +- nexpose.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index d2d4ed1a..b9db6123 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -29,4 +29,4 @@ jobs: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: Run tests - run: bundle exec rake + run: bundle exec rspec --color --format=documentation diff --git a/nexpose.gemspec b/nexpose.gemspec index 6286ca87..abc0b23e 100644 --- a/nexpose.gemspec +++ b/nexpose.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 2.1' s.platform = 'ruby' - s.add_development_dependency('bundler', '~> 1.3') + s.add_development_dependency('bundler') s.add_development_dependency('codeclimate-test-reporter', '~> 0.4.6') s.add_development_dependency('simplecov', '~> 0.9.1') s.add_development_dependency('rake') From 532031167447b883dbfb289370cc376558e07b3d Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Mon, 11 Jan 2021 18:52:36 -0600 Subject: [PATCH 38/58] Add more rubies to github action --- .github/workflows/ruby.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index b9db6123..81369b23 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -11,15 +11,17 @@ on: push: branches: [ master ] pull_request: - branches: [ master ] + schedule: + - '0 0 1 * *' jobs: test: - + name: 'Ruby: ${{ matrix.ruby-version }}' runs-on: ubuntu-latest strategy: + fail-fast: false matrix: - ruby-version: ['2.5', '2.6', '2.7', '3.0'] + ruby-version: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0'] steps: - uses: actions/checkout@v2 @@ -29,4 +31,4 @@ jobs: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: Run tests - run: bundle exec rspec --color --format=documentation + run: bundle exec rspec From 0fd84e82f70263abed0ad9180dff2bbbd07d5c0f Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Mon, 11 Jan 2021 18:54:39 -0600 Subject: [PATCH 39/58] fix syntax issue in workflow --- .github/workflows/ruby.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 81369b23..562622e3 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -11,6 +11,8 @@ on: push: branches: [ master ] pull_request: + branches: + - '*' schedule: - '0 0 1 * *' From ba50c226bcf17962622e24c7c360957e1fafa041 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Mon, 11 Jan 2021 18:58:15 -0600 Subject: [PATCH 40/58] remove schedule from workflow --- .github/workflows/ruby.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 562622e3..e337a43b 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -7,14 +7,7 @@ name: Ruby -on: - push: - branches: [ master ] - pull_request: - branches: - - '*' - schedule: - - '0 0 1 * *' +on: [push, pull_request] jobs: test: From 00d9f52259655da9361a2cc8256ccbf00e4d4b9a Mon Sep 17 00:00:00 2001 From: Adam Bunn Date: Wed, 13 Jan 2021 13:39:45 -0500 Subject: [PATCH 41/58] Update util.rb --- lib/nexpose/util.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nexpose/util.rb b/lib/nexpose/util.rb index 2cbebdee..2a5ecc01 100644 --- a/lib/nexpose/util.rb +++ b/lib/nexpose/util.rb @@ -56,6 +56,7 @@ def convert(asset) IPRange.new(ips[0], ips[1]) rescue ArgumentError => e if e.message =~ /invalid address/ + # Try to parse the the asset as a hostname if the IP address conversion fails HostName.new(asset) else raise "Unable to parse asset: '#{asset}'. #{e.message}" From 5d5674758f25634e1592958d70c2b6546d1bb7d1 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Wed, 13 Jan 2021 17:44:30 -0600 Subject: [PATCH 42/58] Fix test code using invalid constructor --- spec/nexpose/discovery_connection_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/nexpose/discovery_connection_spec.rb b/spec/nexpose/discovery_connection_spec.rb index 698b8f87..30f1c566 100644 --- a/spec/nexpose/discovery_connection_spec.rb +++ b/spec/nexpose/discovery_connection_spec.rb @@ -8,7 +8,7 @@ end it 'sends a request to create the connection' do - xml = REXML::Element.new(%()) + xml = REXML::Document.new(%()) response = double(:response, res: xml, success: true) nexpose_connection = Nexpose::Connection.new('example-host.local', 'johndoe', 'password123') expect(nexpose_connection).to receive(:make_xml) @@ -30,7 +30,7 @@ end it 'sends a request to update the connection' do - xml = REXML::Element.new(%()) + xml = REXML::Document.new(%()) response = double(:response, res: xml, success: true) nexpose_connection = Nexpose::Connection.new('example-host.local', 'johndoe', 'password123') expect(nexpose_connection).to receive(:make_xml) From ac82b2937129a737e6599375d34dc4cb99bba3c0 Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Fri, 2 Apr 2021 11:29:12 -0500 Subject: [PATCH 43/58] update rake task for changelog --- CHANGELOG.md | 136 +++++++++++++++++++++++++++++++++++++++++++++------ Rakefile | 2 + 2 files changed, 123 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d02038bb..b7700ce6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,29 @@ -# Change Log +# Changelog + +## [Unreleased](https://github.com/rapid7/nexpose-client/tree/HEAD) + +[Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.2.1...HEAD) + +**Fixed bugs:** + +- Login Failed when update nexpose-client 2.0.2 to 7.2.1 [\#324](https://github.com/rapid7/nexpose-client/issues/324) + +**Closed issues:** + +- Stuck on maintenance mode page [\#327](https://github.com/rapid7/nexpose-client/issues/327) +- job failure in servicenow [\#323](https://github.com/rapid7/nexpose-client/issues/323) +- \[QUESTION\] How to generate Shared Secret via RESTful API? [\#322](https://github.com/rapid7/nexpose-client/issues/322) +- XML::VulnerabilityDetail/Complete API missing an instances value for vulnerabilities [\#306](https://github.com/rapid7/nexpose-client/issues/306) + +**Merged pull requests:** + +- Add a new privilege ManageAdvPolicies [\#330](https://github.com/rapid7/nexpose-client/pull/330) ([jinq102030](https://github.com/jinq102030)) +- Fix HostOrIP for Ruby 2.6.3 [\#328](https://github.com/rapid7/nexpose-client/pull/328) ([abunn-r7](https://github.com/abunn-r7)) +- Fix travis builds [\#326](https://github.com/rapid7/nexpose-client/pull/326) ([gschneider-r7](https://github.com/gschneider-r7)) +- Migrate eso-client to nexpose-client / CSRF header update [\#309](https://github.com/rapid7/nexpose-client/pull/309) ([hwilson-r7](https://github.com/hwilson-r7)) ## [v7.2.1](https://github.com/rapid7/nexpose-client/tree/v7.2.1) (2018-06-01) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.2.0...v7.2.1) **Closed issues:** @@ -14,6 +37,7 @@ - When passed a filename, download a report in chunks [\#321](https://github.com/rapid7/nexpose-client/pull/321) ([toofishes](https://github.com/toofishes)) ## [v7.2.0](https://github.com/rapid7/nexpose-client/tree/v7.2.0) (2018-01-17) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.1.1...v7.2.0) **Closed issues:** @@ -27,9 +51,9 @@ - Update vuln exceptions to use generally available API version [\#313](https://github.com/rapid7/nexpose-client/pull/313) ([mhuffman-r7](https://github.com/mhuffman-r7)) - Add a method to add common vuln status filters to report configs [\#303](https://github.com/rapid7/nexpose-client/pull/303) ([gschneider-r7](https://github.com/gschneider-r7)) -- Updated for Ruby 2.4 Support [\#301](https://github.com/rapid7/nexpose-client/pull/301) ([twosevenzero](https://github.com/twosevenzero)) ## [v7.1.1](https://github.com/rapid7/nexpose-client/tree/v7.1.1) (2017-09-28) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.1.0...v7.1.1) **Merged pull requests:** @@ -37,6 +61,7 @@ - Some methods were not honoring custom Connection Timeouts [\#300](https://github.com/rapid7/nexpose-client/pull/300) ([sgreen-r7](https://github.com/sgreen-r7)) ## [v7.1.0](https://github.com/rapid7/nexpose-client/tree/v7.1.0) (2017-09-26) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.0.1...v7.1.0) **Fixed bugs:** @@ -54,18 +79,20 @@ **Merged pull requests:** - adding the ability to include a password when restoring a backup [\#298](https://github.com/rapid7/nexpose-client/pull/298) ([sgreen-r7](https://github.com/sgreen-r7)) -- Allow for Starting Scan during Blackout [\#297](https://github.com/rapid7/nexpose-client/pull/297) ([sgreen-r7](https://github.com/sgreen-r7)) ## [v7.0.1](https://github.com/rapid7/nexpose-client/tree/v7.0.1) (2017-09-11) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.0.0...v7.0.1) **Merged pull requests:** +- Allow for Starting Scan during Blackout [\#297](https://github.com/rapid7/nexpose-client/pull/297) ([sgreen-r7](https://github.com/sgreen-r7)) - Only Cleanup!! v3 [\#295](https://github.com/rapid7/nexpose-client/pull/295) ([sgreen-r7](https://github.com/sgreen-r7)) - Revert "Only Cleanup!" [\#293](https://github.com/rapid7/nexpose-client/pull/293) ([sgreen-r7](https://github.com/sgreen-r7)) - Only Cleanup! [\#292](https://github.com/rapid7/nexpose-client/pull/292) ([sgreen-r7](https://github.com/sgreen-r7)) ## [v7.0.0](https://github.com/rapid7/nexpose-client/tree/v7.0.0) (2017-08-31) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v6.1.1...v7.0.0) **Fixed bugs:** @@ -88,9 +115,11 @@ - Bug fixes for adhoc scan with hostname and dynamic asset group description [\#276](https://github.com/rapid7/nexpose-client/pull/276) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v6.1.1](https://github.com/rapid7/nexpose-client/tree/v6.1.1) (2017-07-24) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v6.1.0...v6.1.1) ## [v6.1.0](https://github.com/rapid7/nexpose-client/tree/v6.1.0) (2017-06-19) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v6.0.0...v6.1.0) **Closed issues:** @@ -98,6 +127,7 @@ - Please make engine pool available in ScanData, ScanSummary. [\#277](https://github.com/rapid7/nexpose-client/issues/277) ## [v6.0.0](https://github.com/rapid7/nexpose-client/tree/v6.0.0) (2017-04-03) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v5.3.2...v6.0.0) **Fixed bugs:** @@ -109,6 +139,7 @@ - adding support for listing vuln exceptions on asset groups [\#266](https://github.com/rapid7/nexpose-client/pull/266) ([sgreen-r7](https://github.com/sgreen-r7)) ## [v5.3.2](https://github.com/rapid7/nexpose-client/tree/v5.3.2) (2017-03-28) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v5.3.1...v5.3.2) **Fixed bugs:** @@ -120,6 +151,7 @@ - set blackout enabled [\#265](https://github.com/rapid7/nexpose-client/pull/265) ([dmurray-r7](https://github.com/dmurray-r7)) ## [v5.3.1](https://github.com/rapid7/nexpose-client/tree/v5.3.1) (2017-03-01) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v5.3.0...v5.3.1) **Closed issues:** @@ -131,6 +163,7 @@ - added specific test method for shared creds to use correct attrs [\#262](https://github.com/rapid7/nexpose-client/pull/262) ([sgreen-r7](https://github.com/sgreen-r7)) ## [v5.3.0](https://github.com/rapid7/nexpose-client/tree/v5.3.0) (2017-02-14) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v5.2.0...v5.3.0) **Merged pull requests:** @@ -139,6 +172,7 @@ - allow user to supply a cerificate file for trusted SSL [\#254](https://github.com/rapid7/nexpose-client/pull/254) ([jmartin-r7](https://github.com/jmartin-r7)) ## [v5.2.0](https://github.com/rapid7/nexpose-client/tree/v5.2.0) (2017-01-31) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v5.1.0...v5.2.0) **Fixed bugs:** @@ -162,6 +196,7 @@ - add Connection:update\_engine [\#227](https://github.com/rapid7/nexpose-client/pull/227) ([nbirnel](https://github.com/nbirnel)) ## [v5.1.0](https://github.com/rapid7/nexpose-client/tree/v5.1.0) (2016-08-26) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v5.0.0...v5.1.0) **Fixed bugs:** @@ -171,10 +206,12 @@ **Merged pull requests:** - Add Unique ID support to Asset and ExternalAsset [\#241](https://github.com/rapid7/nexpose-client/pull/241) ([gschneider-r7](https://github.com/gschneider-r7)) +- api delete fix [\#230](https://github.com/rapid7/nexpose-client/pull/230) ([dmurray-r7](https://github.com/dmurray-r7)) - first attempt for fix of hash failure of blackouts [\#226](https://github.com/rapid7/nexpose-client/pull/226) ([sgreen-r7](https://github.com/sgreen-r7)) - Use latest minor versions of Ruby in Travis-CI [\#218](https://github.com/rapid7/nexpose-client/pull/218) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v5.0.0](https://github.com/rapid7/nexpose-client/tree/v5.0.0) (2016-06-23) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v4.0.5...v5.0.0) **Fixed bugs:** @@ -188,6 +225,7 @@ - Fix incorrect documentation for schedule time format [\#232](https://github.com/rapid7/nexpose-client/pull/232) ([dmurray-r7](https://github.com/dmurray-r7)) ## [v4.0.5](https://github.com/rapid7/nexpose-client/tree/v4.0.5) (2016-06-02) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v4.0.4...v4.0.5) **Closed issues:** @@ -197,12 +235,13 @@ **Merged pull requests:** - \#233: Fixed parsing of completed asset response to use correct asset ID [\#234](https://github.com/rapid7/nexpose-client/pull/234) ([mhuffman-r7](https://github.com/mhuffman-r7)) -- api delete fix [\#230](https://github.com/rapid7/nexpose-client/pull/230) ([dmurray-r7](https://github.com/dmurray-r7)) ## [v4.0.4](https://github.com/rapid7/nexpose-client/tree/v4.0.4) (2016-05-17) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v4.0.3...v4.0.4) ## [v4.0.3](https://github.com/rapid7/nexpose-client/tree/v4.0.3) (2016-05-11) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v4.0.2...v4.0.3) **Fixed bugs:** @@ -210,12 +249,15 @@ - Increase REXML::Security.entity\_expansion\_text\_limit [\#229](https://github.com/rapid7/nexpose-client/pull/229) ([sgreen-r7](https://github.com/sgreen-r7)) ## [v4.0.2](https://github.com/rapid7/nexpose-client/tree/v4.0.2) (2016-05-06) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v4.0.1...v4.0.2) ## [v4.0.1](https://github.com/rapid7/nexpose-client/tree/v4.0.1) (2016-05-06) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v4.0.0...v4.0.1) ## [v4.0.0](https://github.com/rapid7/nexpose-client/tree/v4.0.0) (2016-05-05) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v3.3.2...v4.0.0) **Closed issues:** @@ -224,10 +266,10 @@ **Merged pull requests:** -- Add new filter and update IP address operators [\#224](https://github.com/rapid7/nexpose-client/pull/224) ([rkhalil-r7](https://github.com/rkhalil-r7)) - Allow import scan to return scan ID when available [\#223](https://github.com/rapid7/nexpose-client/pull/223) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v3.3.2](https://github.com/rapid7/nexpose-client/tree/v3.3.2) (2016-04-29) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v3.3.1...v3.3.2) **Fixed bugs:** @@ -246,6 +288,7 @@ - Make HostOrIP\#convert more flexible on IP address range input [\#214](https://github.com/rapid7/nexpose-client/pull/214) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v3.3.1](https://github.com/rapid7/nexpose-client/tree/v3.3.1) (2016-04-08) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v3.3.0...v3.3.1) **Fixed bugs:** @@ -255,25 +298,28 @@ **Closed issues:** - Unable to retrieve proofs [\#213](https://github.com/rapid7/nexpose-client/issues/213) +- Adding criteria to tag. [\#209](https://github.com/rapid7/nexpose-client/issues/209) **Merged pull requests:** - Fixing variable references in the to-headers call [\#216](https://github.com/rapid7/nexpose-client/pull/216) ([mhuffman-r7](https://github.com/mhuffman-r7)) ## [v3.3.0](https://github.com/rapid7/nexpose-client/tree/v3.3.0) (2016-04-06) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v3.2.0...v3.3.0) **Closed issues:** - Return nexpose\_id via API using vulnid [\#210](https://github.com/rapid7/nexpose-client/issues/210) -- Adding criteria to tag. [\#209](https://github.com/rapid7/nexpose-client/issues/209) **Merged pull requests:** +- Add new filter and update IP address operators [\#224](https://github.com/rapid7/nexpose-client/pull/224) ([rkhalil-r7](https://github.com/rkhalil-r7)) - Add method for returning the version information for each scan engine [\#212](https://github.com/rapid7/nexpose-client/pull/212) ([Red5d](https://github.com/Red5d)) - Scheduled Backup and Maintenance [\#211](https://github.com/rapid7/nexpose-client/pull/211) ([dmurray-r7](https://github.com/dmurray-r7)) ## [v3.2.0](https://github.com/rapid7/nexpose-client/tree/v3.2.0) (2016-01-20) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v3.1.0...v3.2.0) **Merged pull requests:** @@ -281,6 +327,7 @@ - Windows services editor option [\#207](https://github.com/rapid7/nexpose-client/pull/207) ([kprzerwa-r7](https://github.com/kprzerwa-r7)) ## [v3.1.0](https://github.com/rapid7/nexpose-client/tree/v3.1.0) (2016-01-06) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v3.0.1...v3.1.0) **Merged pull requests:** @@ -288,9 +335,11 @@ - Two factor authentication [\#206](https://github.com/rapid7/nexpose-client/pull/206) ([dsadgat-r7](https://github.com/dsadgat-r7)) ## [v3.0.1](https://github.com/rapid7/nexpose-client/tree/v3.0.1) (2015-12-11) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v3.0.0...v3.0.1) ## [v3.0.0](https://github.com/rapid7/nexpose-client/tree/v3.0.0) (2015-12-11) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v2.3.0...v3.0.0) **Closed issues:** @@ -308,6 +357,7 @@ - Remove deprecated method aliases [\#184](https://github.com/rapid7/nexpose-client/pull/184) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v2.3.0](https://github.com/rapid7/nexpose-client/tree/v2.3.0) (2015-12-10) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v2.2.0...v2.3.0) **Merged pull requests:** @@ -315,6 +365,7 @@ - Add support for modifying the asset linking global preference [\#202](https://github.com/rapid7/nexpose-client/pull/202) ([erran-r7](https://github.com/erran-r7)) ## [v2.2.0](https://github.com/rapid7/nexpose-client/tree/v2.2.0) (2015-12-01) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v2.1.3...v2.2.0) **Merged pull requests:** @@ -322,6 +373,7 @@ - Add methods to enable debug/enhanced logging in the scan template. [\#197](https://github.com/rapid7/nexpose-client/pull/197) ([xliu-r7](https://github.com/xliu-r7)) ## [v2.1.3](https://github.com/rapid7/nexpose-client/tree/v2.1.3) (2015-11-23) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v2.1.2...v2.1.3) **Merged pull requests:** @@ -330,6 +382,7 @@ - Update documentation for list\_device\_vulns [\#194](https://github.com/rapid7/nexpose-client/pull/194) ([rchen-r7](https://github.com/rchen-r7)) ## [v2.1.2](https://github.com/rapid7/nexpose-client/tree/v2.1.2) (2015-11-04) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v2.1.1...v2.1.2) **Closed issues:** @@ -342,6 +395,7 @@ - Use a block with file.new to auto-close file ref [\#191](https://github.com/rapid7/nexpose-client/pull/191) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v2.1.1](https://github.com/rapid7/nexpose-client/tree/v2.1.1) (2015-10-21) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v2.1.0...v2.1.1) **Merged pull requests:** @@ -349,6 +403,7 @@ - Update URLs for NSC config [\#189](https://github.com/rapid7/nexpose-client/pull/189) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v2.1.0](https://github.com/rapid7/nexpose-client/tree/v2.1.0) (2015-10-07) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v2.0.2...v2.1.0) **Fixed bugs:** @@ -370,9 +425,11 @@ - Add methods for changing and querying a scan template's ACES logging level [\#187](https://github.com/rapid7/nexpose-client/pull/187) ([tomhart-r7](https://github.com/tomhart-r7)) ## [v2.0.2](https://github.com/rapid7/nexpose-client/tree/v2.0.2) (2015-08-13) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v2.0.1...v2.0.2) ## [v2.0.1](https://github.com/rapid7/nexpose-client/tree/v2.0.1) (2015-08-07) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v2.0.0...v2.0.1) **Merged pull requests:** @@ -381,6 +438,7 @@ - Updated endpoints for txml removals [\#181](https://github.com/rapid7/nexpose-client/pull/181) ([btrujillo-r7](https://github.com/btrujillo-r7)) ## [v2.0.0](https://github.com/rapid7/nexpose-client/tree/v2.0.0) (2015-07-16) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v1.3.0...v2.0.0) **Fixed bugs:** @@ -393,6 +451,7 @@ - Password policy expiration [\#180](https://github.com/rapid7/nexpose-client/pull/180) ([dmurray-r7](https://github.com/dmurray-r7)) ## [v1.3.0](https://github.com/rapid7/nexpose-client/tree/v1.3.0) (2015-07-07) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v1.2.0...v1.3.0) **Fixed bugs:** @@ -404,6 +463,7 @@ - Update FilteredAsset to support site\_id in Nexpose 5.13 and later [\#179](https://github.com/rapid7/nexpose-client/pull/179) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v1.2.0](https://github.com/rapid7/nexpose-client/tree/v1.2.0) (2015-06-24) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v1.1.0...v1.2.0) **Merged pull requests:** @@ -411,6 +471,7 @@ - Add new syslog constants [\#177](https://github.com/rapid7/nexpose-client/pull/177) ([erran-r7](https://github.com/erran-r7)) ## [v1.1.0](https://github.com/rapid7/nexpose-client/tree/v1.1.0) (2015-05-29) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v1.0.0...v1.1.0) **Fixed bugs:** @@ -434,6 +495,7 @@ - Add DHCP Protocol/Type constants to the DiscoveryConnection class [\#164](https://github.com/rapid7/nexpose-client/pull/164) ([erran-r7](https://github.com/erran-r7)) ## [v1.0.0](https://github.com/rapid7/nexpose-client/tree/v1.0.0) (2015-04-08) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.9.8...v1.0.0) **Closed issues:** @@ -458,16 +520,18 @@ - site-api/site: collapse include\_asset methods and add deprecrated methods [\#138](https://github.com/rapid7/nexpose-client/pull/138) ([gschneider-r7](https://github.com/gschneider-r7)) - site-api/alert: address some of hound's comments [\#137](https://github.com/rapid7/nexpose-client/pull/137) ([gschneider-r7](https://github.com/gschneider-r7)) - Site api [\#135](https://github.com/rapid7/nexpose-client/pull/135) ([gperez-r7](https://github.com/gperez-r7)) +- Remove Ruby 1.9.3 support, require Ruby 2.1.5 [\#134](https://github.com/rapid7/nexpose-client/pull/134) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v0.9.8](https://github.com/rapid7/nexpose-client/tree/v0.9.8) (2015-03-17) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.9.7...v0.9.8) **Merged pull requests:** - Update Nexpose::ScanTemplate methods for device and service discovery [\#136](https://github.com/rapid7/nexpose-client/pull/136) ([jhart-r7](https://github.com/jhart-r7)) -- Remove Ruby 1.9.3 support, require Ruby 2.1.5 [\#134](https://github.com/rapid7/nexpose-client/pull/134) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v0.9.7](https://github.com/rapid7/nexpose-client/tree/v0.9.7) (2015-03-17) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.9.6...v0.9.7) **Merged pull requests:** @@ -475,6 +539,7 @@ - Allow control of device discovery and other template options [\#133](https://github.com/rapid7/nexpose-client/pull/133) ([jhart-r7](https://github.com/jhart-r7)) ## [v0.9.6](https://github.com/rapid7/nexpose-client/tree/v0.9.6) (2015-03-05) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.9.5...v0.9.6) **Fixed bugs:** @@ -500,6 +565,7 @@ - Exclude assets by IP, hostname, or IP ranges from site [\#109](https://github.com/rapid7/nexpose-client/pull/109) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v0.9.5](https://github.com/rapid7/nexpose-client/tree/v0.9.5) (2015-02-09) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.9.4...v0.9.5) **Merged pull requests:** @@ -508,6 +574,7 @@ - Add gschneider to gem authors [\#105](https://github.com/rapid7/nexpose-client/pull/105) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v0.9.4](https://github.com/rapid7/nexpose-client/tree/v0.9.4) (2015-01-28) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.9.3...v0.9.4) **Merged pull requests:** @@ -516,6 +583,7 @@ - fix shared credentials xml element to correctly grab service type [\#102](https://github.com/rapid7/nexpose-client/pull/102) ([sgreen-r7](https://github.com/sgreen-r7)) ## [v0.9.3](https://github.com/rapid7/nexpose-client/tree/v0.9.3) (2015-01-05) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.9.2...v0.9.3) **Merged pull requests:** @@ -523,6 +591,7 @@ - Ajax clean up [\#101](https://github.com/rapid7/nexpose-client/pull/101) ([mdaines-r7](https://github.com/mdaines-r7)) ## [v0.9.2](https://github.com/rapid7/nexpose-client/tree/v0.9.2) (2015-01-05) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.9.1...v0.9.2) **Closed issues:** @@ -530,9 +599,11 @@ - Extract Common Credential Module [\#96](https://github.com/rapid7/nexpose-client/issues/96) ## [v0.9.1](https://github.com/rapid7/nexpose-client/tree/v0.9.1) (2015-01-02) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.9.0...v0.9.1) ## [v0.9.0](https://github.com/rapid7/nexpose-client/tree/v0.9.0) (2014-12-31) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.18...v0.9.0) **Closed issues:** @@ -544,22 +615,26 @@ **Merged pull requests:** - Update to the new username attr for xml [\#100](https://github.com/rapid7/nexpose-client/pull/100) ([sgreen-r7](https://github.com/sgreen-r7)) -- Refactor/Extract Common Credential Module [\#98](https://github.com/rapid7/nexpose-client/pull/98) ([sgreen-r7](https://github.com/sgreen-r7)) ## [v0.8.18](https://github.com/rapid7/nexpose-client/tree/v0.8.18) (2014-12-15) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.17...v0.8.18) ## [v0.8.17](https://github.com/rapid7/nexpose-client/tree/v0.8.17) (2014-12-11) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.16...v0.8.17) ## [v0.8.16](https://github.com/rapid7/nexpose-client/tree/v0.8.16) (2014-12-10) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.15...v0.8.16) **Merged pull requests:** +- Refactor/Extract Common Credential Module [\#98](https://github.com/rapid7/nexpose-client/pull/98) ([sgreen-r7](https://github.com/sgreen-r7)) - Add incomplete\_assets method [\#93](https://github.com/rapid7/nexpose-client/pull/93) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v0.8.15](https://github.com/rapid7/nexpose-client/tree/v0.8.15) (2014-11-12) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.14...v0.8.15) **Closed issues:** @@ -571,9 +646,11 @@ - allow creating vuln exception with site scope [\#91](https://github.com/rapid7/nexpose-client/pull/91) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v0.8.14](https://github.com/rapid7/nexpose-client/tree/v0.8.14) (2014-11-11) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.13...v0.8.14) ## [v0.8.13](https://github.com/rapid7/nexpose-client/tree/v0.8.13) (2014-11-05) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.12...v0.8.13) **Merged pull requests:** @@ -581,6 +658,7 @@ - Expose scan template level control scanning options [\#88](https://github.com/rapid7/nexpose-client/pull/88) ([erran](https://github.com/erran)) ## [v0.8.12](https://github.com/rapid7/nexpose-client/tree/v0.8.12) (2014-11-05) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.11...v0.8.12) **Merged pull requests:** @@ -589,6 +667,7 @@ - Use attr\_accessor instead of a custom setter in GlobalSettings [\#89](https://github.com/rapid7/nexpose-client/pull/89) ([erran](https://github.com/erran)) ## [v0.8.11](https://github.com/rapid7/nexpose-client/tree/v0.8.11) (2014-11-04) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.10...v0.8.11) **Merged pull requests:** @@ -597,6 +676,7 @@ - Use bundler for gem tasks [\#86](https://github.com/rapid7/nexpose-client/pull/86) ([erran](https://github.com/erran)) ## [v0.8.10](https://github.com/rapid7/nexpose-client/tree/v0.8.10) (2014-10-29) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.9...v0.8.10) **Closed issues:** @@ -608,12 +688,15 @@ - Support mobile dynamic connections [\#85](https://github.com/rapid7/nexpose-client/pull/85) ([rtaylor-r7](https://github.com/rtaylor-r7)) ## [v0.8.9](https://github.com/rapid7/nexpose-client/tree/v0.8.9) (2014-10-20) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.8...v0.8.9) ## [v0.8.8](https://github.com/rapid7/nexpose-client/tree/v0.8.8) (2014-10-17) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.7...v0.8.8) ## [v0.8.7](https://github.com/rapid7/nexpose-client/tree/v0.8.7) (2014-10-14) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.6...v0.8.7) **Closed issues:** @@ -621,6 +704,7 @@ - Error When Loading Dynamic Sites [\#83](https://github.com/rapid7/nexpose-client/issues/83) ## [v0.8.6](https://github.com/rapid7/nexpose-client/tree/v0.8.6) (2014-10-13) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.5...v0.8.6) **Closed issues:** @@ -628,6 +712,7 @@ - Site.save is not functioning for dynamic sites [\#71](https://github.com/rapid7/nexpose-client/issues/71) ## [v0.8.5](https://github.com/rapid7/nexpose-client/tree/v0.8.5) (2014-10-09) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.1...v0.8.5) **Closed issues:** @@ -644,6 +729,7 @@ - Add support for new Description tag in site and group configs [\#70](https://github.com/rapid7/nexpose-client/pull/70) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v0.8.1](https://github.com/rapid7/nexpose-client/tree/v0.8.1) (2014-07-03) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.8.0...v0.8.1) **Merged pull requests:** @@ -652,6 +738,7 @@ - SNMP v3 credential support [\#67](https://github.com/rapid7/nexpose-client/pull/67) ([kprzerwa-r7](https://github.com/kprzerwa-r7)) ## [v0.8.0](https://github.com/rapid7/nexpose-client/tree/v0.8.0) (2014-06-13) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.7.6...v0.8.0) **Merged pull requests:** @@ -659,14 +746,15 @@ - An incorrect type when parsing JSON in the Asset class for initialization [\#66](https://github.com/rapid7/nexpose-client/pull/66) ([DevinCarr](https://github.com/DevinCarr)) ## [v0.7.6](https://github.com/rapid7/nexpose-client/tree/v0.7.6) (2014-06-06) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.7.5...v0.7.6) **Merged pull requests:** - Add methods to scan\_template.rb to enable port exclusion. [\#65](https://github.com/rapid7/nexpose-client/pull/65) ([AdamBunn](https://github.com/AdamBunn)) -- Validate and raise error for unsupported colors [\#64](https://github.com/rapid7/nexpose-client/pull/64) ([erran](https://github.com/erran)) ## [v0.7.5](https://github.com/rapid7/nexpose-client/tree/v0.7.5) (2014-05-23) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.7.4...v0.7.5) **Merged pull requests:** @@ -674,6 +762,7 @@ - Add tag filter to doc [\#63](https://github.com/rapid7/nexpose-client/pull/63) ([zachrab](https://github.com/zachrab)) ## [v0.7.4](https://github.com/rapid7/nexpose-client/tree/v0.7.4) (2014-05-07) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.7.3...v0.7.4) **Merged pull requests:** @@ -681,6 +770,7 @@ - Fixed escaping in Roles [\#62](https://github.com/rapid7/nexpose-client/pull/62) ([asalazar-r7](https://github.com/asalazar-r7)) ## [v0.7.3](https://github.com/rapid7/nexpose-client/tree/v0.7.3) (2014-04-30) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.7.2...v0.7.3) **Merged pull requests:** @@ -688,6 +778,7 @@ - Fix updates on Roles. [\#61](https://github.com/rapid7/nexpose-client/pull/61) ([kkohli-r7](https://github.com/kkohli-r7)) ## [v0.7.2](https://github.com/rapid7/nexpose-client/tree/v0.7.2) (2014-04-29) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.7.1...v0.7.2) **Closed issues:** @@ -696,13 +787,14 @@ **Merged pull requests:** -- Set role.id to -1 by default on initialization [\#60](https://github.com/rapid7/nexpose-client/pull/60) ([erran](https://github.com/erran)) - Add controls-insight-only as a valid role [\#58](https://github.com/rapid7/nexpose-client/pull/58) ([erran](https://github.com/erran)) ## [v0.7.1](https://github.com/rapid7/nexpose-client/tree/v0.7.1) (2014-04-10) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.7.0...v0.7.1) ## [v0.7.0](https://github.com/rapid7/nexpose-client/tree/v0.7.0) (2014-03-26) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.6.5...v0.7.0) **Closed issues:** @@ -714,12 +806,16 @@ **Merged pull requests:** +- Validate and raise error for unsupported colors [\#64](https://github.com/rapid7/nexpose-client/pull/64) ([erran](https://github.com/erran)) +- Set role.id to -1 by default on initialization [\#60](https://github.com/rapid7/nexpose-client/pull/60) ([erran](https://github.com/erran)) - Changes for criticality tags and associated assets [\#56](https://github.com/rapid7/nexpose-client/pull/56) ([zachrab](https://github.com/zachrab)) - Ivan - Support for tags [\#55](https://github.com/rapid7/nexpose-client/pull/55) ([kkohli-r7](https://github.com/kkohli-r7)) - Minor licensing and naming updates [\#54](https://github.com/rapid7/nexpose-client/pull/54) ([todb-r7](https://github.com/todb-r7)) - Updating Silo functionality in the Gem [\#52](https://github.com/rapid7/nexpose-client/pull/52) ([asalazar-r7](https://github.com/asalazar-r7)) +- Fix for dynamic asset group creation [\#51](https://github.com/rapid7/nexpose-client/pull/51) ([zachrab](https://github.com/zachrab)) ## [v0.6.5](https://github.com/rapid7/nexpose-client/tree/v0.6.5) (2014-03-11) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.6.4...v0.6.5) **Closed issues:** @@ -727,13 +823,11 @@ - Site class missing organization attributes [\#53](https://github.com/rapid7/nexpose-client/issues/53) ## [v0.6.4](https://github.com/rapid7/nexpose-client/tree/v0.6.4) (2014-03-10) -[Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.6.3...v0.6.4) - -**Merged pull requests:** -- Fix for dynamic asset group creation [\#51](https://github.com/rapid7/nexpose-client/pull/51) ([zachrab](https://github.com/zachrab)) +[Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.6.3...v0.6.4) ## [v0.6.3](https://github.com/rapid7/nexpose-client/tree/v0.6.3) (2014-02-25) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.6.2...v0.6.3) **Closed issues:** @@ -743,6 +837,7 @@ - Nexpose::ReportConfig.build incorrectly adds frequency when generate\_now is true [\#43](https://github.com/rapid7/nexpose-client/issues/43) ## [v0.6.2](https://github.com/rapid7/nexpose-client/tree/v0.6.2) (2014-01-30) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.6.1...v0.6.2) **Closed issues:** @@ -753,9 +848,11 @@ - After a successful authentication, session\_id is nil since gem version 0.1.3 [\#45](https://github.com/rapid7/nexpose-client/issues/45) ## [v0.6.1](https://github.com/rapid7/nexpose-client/tree/v0.6.1) (2014-01-09) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.6.0...v0.6.1) ## [v0.6.0](https://github.com/rapid7/nexpose-client/tree/v0.6.0) (2013-12-18) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.5.6...v0.6.0) **Merged pull requests:** @@ -763,9 +860,11 @@ - Added equality comparison to report filters and modified single quote XM... [\#42](https://github.com/rapid7/nexpose-client/pull/42) ([zeroorone13](https://github.com/zeroorone13)) ## [v0.5.6](https://github.com/rapid7/nexpose-client/tree/v0.5.6) (2013-11-21) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.5.5...v0.5.6) ## [v0.5.5](https://github.com/rapid7/nexpose-client/tree/v0.5.5) (2013-11-08) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.5.4...v0.5.5) **Closed issues:** @@ -777,9 +876,11 @@ - Fixed call to delete\_device \(method name changed\) [\#41](https://github.com/rapid7/nexpose-client/pull/41) ([pdogg](https://github.com/pdogg)) ## [v0.5.4](https://github.com/rapid7/nexpose-client/tree/v0.5.4) (2013-09-27) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.5.3...v0.5.4) ## [v0.5.3](https://github.com/rapid7/nexpose-client/tree/v0.5.3) (2013-09-27) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.5.2...v0.5.3) **Closed issues:** @@ -787,6 +888,7 @@ - Move NexpoesAPI into a new Nexpose::API module [\#39](https://github.com/rapid7/nexpose-client/issues/39) ## [v0.5.2](https://github.com/rapid7/nexpose-client/tree/v0.5.2) (2013-09-17) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.5.1...v0.5.2) **Closed issues:** @@ -797,6 +899,7 @@ - Nexpose::ReportAdHoc strange behavior with different formats [\#4](https://github.com/rapid7/nexpose-client/issues/4) ## [v0.5.1](https://github.com/rapid7/nexpose-client/tree/v0.5.1) (2013-09-15) + [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v0.5.0...v0.5.1) **Merged pull requests:** @@ -804,6 +907,9 @@ - Allow for Nexpose::Connection.new to consume URI objects [\#38](https://github.com/rapid7/nexpose-client/pull/38) ([erran](https://github.com/erran)) ## [v0.5.0](https://github.com/rapid7/nexpose-client/tree/v0.5.0) (2013-09-01) + +[Full Changelog](https://github.com/rapid7/nexpose-client/compare/47947da8766ff8388850d7ce458898388773c433...v0.5.0) + **Closed issues:** - ReportTemplate delete does not work [\#36](https://github.com/rapid7/nexpose-client/issues/36) @@ -833,4 +939,4 @@ -\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/Rakefile b/Rakefile index 0f7d9728..ae32ca11 100644 --- a/Rakefile +++ b/Rakefile @@ -12,4 +12,6 @@ GitHubChangelogGenerator::RakeTask.new :changelog do |config| if token.nil? warn "!!WARNING!! Missing Github Token Environment Variable. Fix before you run rake changelog. !!WARNING!!" end + config.user = 'rapid7' + config.project = 'nexpose-client' end From 1b5954ff3ab48246a9ebea2b63efe707232211ce Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Fri, 2 Apr 2021 11:30:12 -0500 Subject: [PATCH 44/58] update version for feature release --- lib/nexpose/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nexpose/version.rb b/lib/nexpose/version.rb index 8fcfa6e2..3db3a5e1 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.2.1'.freeze + VERSION = '7.3.0'.freeze end From f1edd8e0e8f5b9b36db254f0ec57dc126e8eb8cf Mon Sep 17 00:00:00 2001 From: Gavin Schneider Date: Fri, 2 Apr 2021 11:50:11 -0500 Subject: [PATCH 45/58] set next version --- CHANGELOG.md | 23 ++++++++++------------- lib/nexpose/version.rb | 2 +- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7700ce6..a68025a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Changelog -## [Unreleased](https://github.com/rapid7/nexpose-client/tree/HEAD) +## [v7.3.0](https://github.com/rapid7/nexpose-client/tree/v7.3.0) (2021-04-02) -[Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.2.1...HEAD) +[Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.2.1...v7.3.0) **Fixed bugs:** @@ -79,6 +79,7 @@ **Merged pull requests:** - adding the ability to include a password when restoring a backup [\#298](https://github.com/rapid7/nexpose-client/pull/298) ([sgreen-r7](https://github.com/sgreen-r7)) +- Allow for Starting Scan during Blackout [\#297](https://github.com/rapid7/nexpose-client/pull/297) ([sgreen-r7](https://github.com/sgreen-r7)) ## [v7.0.1](https://github.com/rapid7/nexpose-client/tree/v7.0.1) (2017-09-11) @@ -86,7 +87,6 @@ **Merged pull requests:** -- Allow for Starting Scan during Blackout [\#297](https://github.com/rapid7/nexpose-client/pull/297) ([sgreen-r7](https://github.com/sgreen-r7)) - Only Cleanup!! v3 [\#295](https://github.com/rapid7/nexpose-client/pull/295) ([sgreen-r7](https://github.com/sgreen-r7)) - Revert "Only Cleanup!" [\#293](https://github.com/rapid7/nexpose-client/pull/293) ([sgreen-r7](https://github.com/sgreen-r7)) - Only Cleanup! [\#292](https://github.com/rapid7/nexpose-client/pull/292) ([sgreen-r7](https://github.com/sgreen-r7)) @@ -206,7 +206,6 @@ **Merged pull requests:** - Add Unique ID support to Asset and ExternalAsset [\#241](https://github.com/rapid7/nexpose-client/pull/241) ([gschneider-r7](https://github.com/gschneider-r7)) -- api delete fix [\#230](https://github.com/rapid7/nexpose-client/pull/230) ([dmurray-r7](https://github.com/dmurray-r7)) - first attempt for fix of hash failure of blackouts [\#226](https://github.com/rapid7/nexpose-client/pull/226) ([sgreen-r7](https://github.com/sgreen-r7)) - Use latest minor versions of Ruby in Travis-CI [\#218](https://github.com/rapid7/nexpose-client/pull/218) ([gschneider-r7](https://github.com/gschneider-r7)) @@ -235,6 +234,7 @@ **Merged pull requests:** - \#233: Fixed parsing of completed asset response to use correct asset ID [\#234](https://github.com/rapid7/nexpose-client/pull/234) ([mhuffman-r7](https://github.com/mhuffman-r7)) +- api delete fix [\#230](https://github.com/rapid7/nexpose-client/pull/230) ([dmurray-r7](https://github.com/dmurray-r7)) ## [v4.0.4](https://github.com/rapid7/nexpose-client/tree/v4.0.4) (2016-05-17) @@ -266,6 +266,7 @@ **Merged pull requests:** +- Add new filter and update IP address operators [\#224](https://github.com/rapid7/nexpose-client/pull/224) ([rkhalil-r7](https://github.com/rkhalil-r7)) - Allow import scan to return scan ID when available [\#223](https://github.com/rapid7/nexpose-client/pull/223) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v3.3.2](https://github.com/rapid7/nexpose-client/tree/v3.3.2) (2016-04-29) @@ -298,7 +299,6 @@ **Closed issues:** - Unable to retrieve proofs [\#213](https://github.com/rapid7/nexpose-client/issues/213) -- Adding criteria to tag. [\#209](https://github.com/rapid7/nexpose-client/issues/209) **Merged pull requests:** @@ -311,10 +311,10 @@ **Closed issues:** - Return nexpose\_id via API using vulnid [\#210](https://github.com/rapid7/nexpose-client/issues/210) +- Adding criteria to tag. [\#209](https://github.com/rapid7/nexpose-client/issues/209) **Merged pull requests:** -- Add new filter and update IP address operators [\#224](https://github.com/rapid7/nexpose-client/pull/224) ([rkhalil-r7](https://github.com/rkhalil-r7)) - Add method for returning the version information for each scan engine [\#212](https://github.com/rapid7/nexpose-client/pull/212) ([Red5d](https://github.com/Red5d)) - Scheduled Backup and Maintenance [\#211](https://github.com/rapid7/nexpose-client/pull/211) ([dmurray-r7](https://github.com/dmurray-r7)) @@ -420,10 +420,6 @@ - Add more engine info and features [\#166](https://github.com/rapid7/nexpose-client/issues/166) - Get asset count and vuln count for Asset Groups [\#130](https://github.com/rapid7/nexpose-client/issues/130) -**Merged pull requests:** - -- Add methods for changing and querying a scan template's ACES logging level [\#187](https://github.com/rapid7/nexpose-client/pull/187) ([tomhart-r7](https://github.com/tomhart-r7)) - ## [v2.0.2](https://github.com/rapid7/nexpose-client/tree/v2.0.2) (2015-08-13) [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v2.0.1...v2.0.2) @@ -448,6 +444,7 @@ **Merged pull requests:** +- Add methods for changing and querying a scan template's ACES logging level [\#187](https://github.com/rapid7/nexpose-client/pull/187) ([tomhart-r7](https://github.com/tomhart-r7)) - Password policy expiration [\#180](https://github.com/rapid7/nexpose-client/pull/180) ([dmurray-r7](https://github.com/dmurray-r7)) ## [v1.3.0](https://github.com/rapid7/nexpose-client/tree/v1.3.0) (2015-07-07) @@ -615,6 +612,7 @@ **Merged pull requests:** - Update to the new username attr for xml [\#100](https://github.com/rapid7/nexpose-client/pull/100) ([sgreen-r7](https://github.com/sgreen-r7)) +- Refactor/Extract Common Credential Module [\#98](https://github.com/rapid7/nexpose-client/pull/98) ([sgreen-r7](https://github.com/sgreen-r7)) ## [v0.8.18](https://github.com/rapid7/nexpose-client/tree/v0.8.18) (2014-12-15) @@ -630,7 +628,6 @@ **Merged pull requests:** -- Refactor/Extract Common Credential Module [\#98](https://github.com/rapid7/nexpose-client/pull/98) ([sgreen-r7](https://github.com/sgreen-r7)) - Add incomplete\_assets method [\#93](https://github.com/rapid7/nexpose-client/pull/93) ([gschneider-r7](https://github.com/gschneider-r7)) ## [v0.8.15](https://github.com/rapid7/nexpose-client/tree/v0.8.15) (2014-11-12) @@ -752,6 +749,7 @@ **Merged pull requests:** - Add methods to scan\_template.rb to enable port exclusion. [\#65](https://github.com/rapid7/nexpose-client/pull/65) ([AdamBunn](https://github.com/AdamBunn)) +- Validate and raise error for unsupported colors [\#64](https://github.com/rapid7/nexpose-client/pull/64) ([erran](https://github.com/erran)) ## [v0.7.5](https://github.com/rapid7/nexpose-client/tree/v0.7.5) (2014-05-23) @@ -787,6 +785,7 @@ **Merged pull requests:** +- Set role.id to -1 by default on initialization [\#60](https://github.com/rapid7/nexpose-client/pull/60) ([erran](https://github.com/erran)) - Add controls-insight-only as a valid role [\#58](https://github.com/rapid7/nexpose-client/pull/58) ([erran](https://github.com/erran)) ## [v0.7.1](https://github.com/rapid7/nexpose-client/tree/v0.7.1) (2014-04-10) @@ -806,8 +805,6 @@ **Merged pull requests:** -- Validate and raise error for unsupported colors [\#64](https://github.com/rapid7/nexpose-client/pull/64) ([erran](https://github.com/erran)) -- Set role.id to -1 by default on initialization [\#60](https://github.com/rapid7/nexpose-client/pull/60) ([erran](https://github.com/erran)) - Changes for criticality tags and associated assets [\#56](https://github.com/rapid7/nexpose-client/pull/56) ([zachrab](https://github.com/zachrab)) - Ivan - Support for tags [\#55](https://github.com/rapid7/nexpose-client/pull/55) ([kkohli-r7](https://github.com/kkohli-r7)) - Minor licensing and naming updates [\#54](https://github.com/rapid7/nexpose-client/pull/54) ([todb-r7](https://github.com/todb-r7)) diff --git a/lib/nexpose/version.rb b/lib/nexpose/version.rb index 3db3a5e1..7e5ac867 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.3.0'.freeze + VERSION = '7.3.1'.freeze end From 8709edddb3c0b87c9683d3f760d53204f32e5db6 Mon Sep 17 00:00:00 2001 From: jsteers-r7 Date: Thu, 3 Feb 2022 17:50:11 +0000 Subject: [PATCH 46/58] Add new oracle service name credential --- lib/nexpose/credential.rb | 2 ++ lib/nexpose/credential_helper.rb | 8 ++++++++ lib/nexpose/site_credentials.rb | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/lib/nexpose/credential.rb b/lib/nexpose/credential.rb index 693b5c4f..cfdead26 100644 --- a/lib/nexpose/credential.rb +++ b/lib/nexpose/credential.rb @@ -16,6 +16,7 @@ class Credential < APIObject 'cifs' => 445, 'cifshash' => 445, 'oracle' => 1521, + 'oracle-service-name' => 1521, 'pop' => 110, 'postgresql' => 5432, 'remote execution' => 512, @@ -46,6 +47,7 @@ module Service CIFS = 'cifs' # Microsoft Windows/Samba (SMB/CIFS) CIFSHASH = 'cifshash' # Microsoft Windows/Samba LM/NTLM Hash (SMB/CIFS) ORACLE = 'oracle' # Oracle + ORACLESERVICENAME = 'oracle-service-name' # Oracle using Service Name Auth POP = 'pop' # Post Office Protocol (POP) POSTGRESQL = 'postgresql' # PostgreSQL REMOTE_EXECUTION = 'remote execution' # Remote Execution diff --git a/lib/nexpose/credential_helper.rb b/lib/nexpose/credential_helper.rb index 4c137aff..8de62259 100644 --- a/lib/nexpose/credential_helper.rb +++ b/lib/nexpose/credential_helper.rb @@ -81,6 +81,14 @@ def set_oracle_service(sid = nil, username = nil, password = nil) self.service = Credential::Service::ORACLE end + # sets the Oracle service using Service Name authentication. + def set_oracle_service_using_service_name_auth(servicename = nil, username = nil, password = nil) + self.database = servicename + self.user_name = username + self.password = password + self.service = Credential::Service::ORACLESERVICENAME + end + # sets the Post Office Protocol (POP) service. def set_pop_service(username = nil, password = nil) self.user_name = username diff --git a/lib/nexpose/site_credentials.rb b/lib/nexpose/site_credentials.rb index 0395f2b5..70be96fc 100644 --- a/lib/nexpose/site_credentials.rb +++ b/lib/nexpose/site_credentials.rb @@ -49,6 +49,8 @@ class SiteCredentials < Credential attr_accessor :use_windows_auth # sid for oracle attr_accessor :sid + # servicename for oracle + attr_accessor :servicename # for ssh public key require pem format private key attr_accessor :pem_format_private_key # for snmp v1/v2 @@ -184,6 +186,7 @@ def to_h notes_id_password: notes_id_password, use_windows_auth: use_windows_auth, sid: sid, + servicename: servicename, pem_format_private_key: pem_format_private_key, community_name: community_name, scope: scope } @@ -214,6 +217,7 @@ def eql?(other) notes_id_password.eql?(other.notes_id_password) && use_windows_auth.eql?(other.use_windows_auth) && sid.eql?(other.sid) && + servicename.eql?(other.servicename) && pem_format_private_key.eql?(other.pem_format_private_key) && community_name.eql?(other.community_name) && scope.eql?(other.scope) From 9a1e2bd0ad408eabe7f432d6cc3f35ba973ed93f Mon Sep 17 00:00:00 2001 From: jsteers-r7 Date: Wed, 9 Feb 2022 12:40:27 +0000 Subject: [PATCH 47/58] Rename oracle-service-name service module --- lib/nexpose/credential.rb | 2 +- lib/nexpose/credential_helper.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nexpose/credential.rb b/lib/nexpose/credential.rb index cfdead26..28e834e1 100644 --- a/lib/nexpose/credential.rb +++ b/lib/nexpose/credential.rb @@ -47,7 +47,7 @@ module Service CIFS = 'cifs' # Microsoft Windows/Samba (SMB/CIFS) CIFSHASH = 'cifshash' # Microsoft Windows/Samba LM/NTLM Hash (SMB/CIFS) ORACLE = 'oracle' # Oracle - ORACLESERVICENAME = 'oracle-service-name' # Oracle using Service Name Auth + ORACLE_SERVICE_NAME = 'oracle-service-name' # Oracle using Service Name Auth POP = 'pop' # Post Office Protocol (POP) POSTGRESQL = 'postgresql' # PostgreSQL REMOTE_EXECUTION = 'remote execution' # Remote Execution diff --git a/lib/nexpose/credential_helper.rb b/lib/nexpose/credential_helper.rb index 8de62259..74e5b37e 100644 --- a/lib/nexpose/credential_helper.rb +++ b/lib/nexpose/credential_helper.rb @@ -86,7 +86,7 @@ def set_oracle_service_using_service_name_auth(servicename = nil, username = nil self.database = servicename self.user_name = username self.password = password - self.service = Credential::Service::ORACLESERVICENAME + self.service = Credential::Service::ORACLE_SERVICE_NAME end # sets the Post Office Protocol (POP) service. From 67eb20c38f3bb1694cb246a35b4fb8ebacaccf57 Mon Sep 17 00:00:00 2001 From: jsteers-r7 Date: Wed, 9 Feb 2022 12:58:39 +0000 Subject: [PATCH 48/58] Use correct syntax for service_name value --- lib/nexpose/credential_helper.rb | 4 ++-- lib/nexpose/site_credentials.rb | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/nexpose/credential_helper.rb b/lib/nexpose/credential_helper.rb index 74e5b37e..b6159112 100644 --- a/lib/nexpose/credential_helper.rb +++ b/lib/nexpose/credential_helper.rb @@ -82,8 +82,8 @@ def set_oracle_service(sid = nil, username = nil, password = nil) end # sets the Oracle service using Service Name authentication. - def set_oracle_service_using_service_name_auth(servicename = nil, username = nil, password = nil) - self.database = servicename + def set_oracle_service_using_service_name_auth(service_name = nil, username = nil, password = nil) + self.database = service_name self.user_name = username self.password = password self.service = Credential::Service::ORACLE_SERVICE_NAME diff --git a/lib/nexpose/site_credentials.rb b/lib/nexpose/site_credentials.rb index 70be96fc..05c16dd2 100644 --- a/lib/nexpose/site_credentials.rb +++ b/lib/nexpose/site_credentials.rb @@ -49,8 +49,8 @@ class SiteCredentials < Credential attr_accessor :use_windows_auth # sid for oracle attr_accessor :sid - # servicename for oracle - attr_accessor :servicename + # service name for oracle + attr_accessor :service_name # for ssh public key require pem format private key attr_accessor :pem_format_private_key # for snmp v1/v2 @@ -186,7 +186,7 @@ def to_h notes_id_password: notes_id_password, use_windows_auth: use_windows_auth, sid: sid, - servicename: servicename, + service_name: service_name, pem_format_private_key: pem_format_private_key, community_name: community_name, scope: scope } @@ -217,7 +217,7 @@ def eql?(other) notes_id_password.eql?(other.notes_id_password) && use_windows_auth.eql?(other.use_windows_auth) && sid.eql?(other.sid) && - servicename.eql?(other.servicename) && + service_name.eql?(other.service_name) && pem_format_private_key.eql?(other.pem_format_private_key) && community_name.eql?(other.community_name) && scope.eql?(other.scope) From 287a1df9cf16445df0d5cda6d644fe1513a83fbd Mon Sep 17 00:00:00 2001 From: Connor Fleming Date: Fri, 27 Jan 2023 11:50:04 +0000 Subject: [PATCH 49/58] Allow setting of invulnerable storage --- lib/nexpose/scan_template.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/nexpose/scan_template.rb b/lib/nexpose/scan_template.rb index 5b2cbb18..5a2439dc 100644 --- a/lib/nexpose/scan_template.rb +++ b/lib/nexpose/scan_template.rb @@ -162,6 +162,19 @@ def web_spidering=(enable) gen.attributes['disableWebSpider'] = enable ? '0' : '1' end + # @return [Boolean] Whether StoreInvulnerableResults in enabled. + def invulnerable_storage? + gen = REXML::XPath.first(@xml, 'ScanTemplate/General') + gen.attributes['invulnerableStorage'] == 'on' + end + + # Adjust whether to Store Invulnerable Results with this template. + # @param [Boolean] enable Whether to StoreInvulnerableResults. + def invulnerable_storage=(enable) + gen = REXML::XPath.first(@xml, 'ScanTemplate/General') + gen.attributes['invulnerableStorage'] = enable ? 'on' : 'off' + end + # Adjust the number of threads to use per scan engine for this template # @param [Integer] threads the number of threads to use per engine def scan_threads=(threads) From cfd7ce763e6ea679918d4604766e18f14cb454e4 Mon Sep 17 00:00:00 2001 From: Connor Fleming Date: Fri, 27 Jan 2023 11:51:58 +0000 Subject: [PATCH 50/58] Reword comments --- lib/nexpose/scan_template.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/nexpose/scan_template.rb b/lib/nexpose/scan_template.rb index 5a2439dc..df4fc538 100644 --- a/lib/nexpose/scan_template.rb +++ b/lib/nexpose/scan_template.rb @@ -162,14 +162,14 @@ def web_spidering=(enable) gen.attributes['disableWebSpider'] = enable ? '0' : '1' end - # @return [Boolean] Whether StoreInvulnerableResults in enabled. + # @return [Boolean] Whether Invulnerable Results is enabled. def invulnerable_storage? gen = REXML::XPath.first(@xml, 'ScanTemplate/General') gen.attributes['invulnerableStorage'] == 'on' end - # Adjust whether to Store Invulnerable Results with this template. - # @param [Boolean] enable Whether to StoreInvulnerableResults. + # Adjust whether to Store Invulnerable results with this template. + # @param [Boolean] enable Whether to Store Invulnerable results. def invulnerable_storage=(enable) gen = REXML::XPath.first(@xml, 'ScanTemplate/General') gen.attributes['invulnerableStorage'] = enable ? 'on' : 'off' From a848eec9cd1da937f48d80d5a4619156ddbb085d Mon Sep 17 00:00:00 2001 From: Simon Irwin Date: Mon, 2 Oct 2023 14:14:17 +0100 Subject: [PATCH 51/58] PD-41096 Auto-add cortex.yaml --- cortex.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 cortex.yaml diff --git a/cortex.yaml b/cortex.yaml new file mode 100644 index 00000000..b89a32b0 --- /dev/null +++ b/cortex.yaml @@ -0,0 +1,15 @@ +--- +info: + title: Nexpose Client + description: 'DEPRECATED: Rapid7 Nexpose API client library written in Ruby' + x-cortex-git: + github: + alias: r7org + repository: rapid7/nexpose-client + x-cortex-tag: nexpose-client + x-cortex-type: service + x-cortex-domain-parents: + - tag: vm-console +openapi: 3.0.1 +servers: +- url: "/" From d9f6691dfe2879f3b93b3dfbb529548358e5a977 Mon Sep 17 00:00:00 2001 From: Kyle McWhirter Date: Fri, 17 Nov 2023 15:50:45 +0000 Subject: [PATCH 52/58] remove preceding slash from url for spring 4.3.30 minor upgrade nexpose --- lib/eso/configuration/configuration_manager.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/eso/configuration/configuration_manager.rb b/lib/eso/configuration/configuration_manager.rb index dcfdd3d0..99487ab0 100644 --- a/lib/eso/configuration/configuration_manager.rb +++ b/lib/eso/configuration/configuration_manager.rb @@ -66,7 +66,7 @@ def configuration_type(service_name:) # return [JSON] A json object representing a configuration # TODO : Update to use an Eso::Configuration def get_configuration(configuration_id) - json_data = ::Nexpose::AJAX.get(@nexpose_console, "#{@url}/service/configuration/id/#{configuration_id}", ::Nexpose::AJAX::CONTENT_TYPE::JSON) + json_data = ::Nexpose::AJAX.get(@nexpose_console, "#{@url}service/configuration/id/#{configuration_id}", ::Nexpose::AJAX::CONTENT_TYPE::JSON) JSON.parse(json_data, :symbolize_names => true) end From db44df5a10bc0ec46838ceaaf785c91d189206ac Mon Sep 17 00:00:00 2001 From: Cian Doherty Date: Wed, 27 Dec 2023 07:29:10 +0000 Subject: [PATCH 53/58] Add missing Investigation privs --- CHANGELOG.md | 9 +++++++++ lib/nexpose/role.rb | 2 ++ lib/nexpose/version.rb | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a68025a2..f765548e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [v7.3.2](https://github.com/rapid7/nexpose-client/tree/v7.3.2) (2023-12-27) + +[Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.3.1...v7.3.2) + +**Merged pull requests:** +- Missing Global Privileges (ViewVulnInvestigations, ManageVulnInvestigations) (https://github.com/rapid7/nexpose-client/pull/337) + +**Fixed bugs:** + ## [v7.3.0](https://github.com/rapid7/nexpose-client/tree/v7.3.0) (2021-04-02) [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.2.1...v7.3.0) diff --git a/lib/nexpose/role.rb b/lib/nexpose/role.rb index 4f2fb2c7..b89f84de 100644 --- a/lib/nexpose/role.rb +++ b/lib/nexpose/role.rb @@ -16,6 +16,8 @@ module Global SUBMIT_VULN_EXCEPTIONS = 'SubmitVulnExceptions' APPROVE_VULN_EXCEPTIONS = 'ApproveVulnExceptions' DELETE_VULN_EXCEPTIONS = 'DeleteVulnExceptions' + VIEW_VULN_INVESTIGATIONS = 'ViewVulnInvestigations' + MANAGE_VULN_INVESTIGATIONS = 'ManageVulnInvestigations' CREATE_TICKETS = 'CreateTickets' CLOSE_TICKETS = 'CloseTickets' TICKET_ASSIGNEE = 'TicketAssignee' diff --git a/lib/nexpose/version.rb b/lib/nexpose/version.rb index 7e5ac867..98d77555 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.3.1'.freeze + VERSION = '7.3.2'.freeze end From 67c5770647e565ba735a10ee32584609e0d30b10 Mon Sep 17 00:00:00 2001 From: Cian Doherty Date: Wed, 27 Dec 2023 08:39:19 +0000 Subject: [PATCH 54/58] remove pr --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f765548e..7f8f4244 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.3.1...v7.3.2) **Merged pull requests:** -- Missing Global Privileges (ViewVulnInvestigations, ManageVulnInvestigations) (https://github.com/rapid7/nexpose-client/pull/337) +- Missing Global Privileges (ViewVulnInvestigations, ManageVulnInvestigations) **Fixed bugs:** From a865a846354e095a8313767c109d79b10d69a2fc Mon Sep 17 00:00:00 2001 From: Connor Fleming Date: Thu, 29 Feb 2024 10:53:00 +0000 Subject: [PATCH 55/58] Revert "NEX-55514 Add missing Privileges to role.rb" --- CHANGELOG.md | 9 --------- lib/nexpose/role.rb | 2 -- lib/nexpose/version.rb | 2 +- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f8f4244..a68025a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,5 @@ # Changelog -## [v7.3.2](https://github.com/rapid7/nexpose-client/tree/v7.3.2) (2023-12-27) - -[Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.3.1...v7.3.2) - -**Merged pull requests:** -- Missing Global Privileges (ViewVulnInvestigations, ManageVulnInvestigations) - -**Fixed bugs:** - ## [v7.3.0](https://github.com/rapid7/nexpose-client/tree/v7.3.0) (2021-04-02) [Full Changelog](https://github.com/rapid7/nexpose-client/compare/v7.2.1...v7.3.0) diff --git a/lib/nexpose/role.rb b/lib/nexpose/role.rb index b89f84de..4f2fb2c7 100644 --- a/lib/nexpose/role.rb +++ b/lib/nexpose/role.rb @@ -16,8 +16,6 @@ module Global SUBMIT_VULN_EXCEPTIONS = 'SubmitVulnExceptions' APPROVE_VULN_EXCEPTIONS = 'ApproveVulnExceptions' DELETE_VULN_EXCEPTIONS = 'DeleteVulnExceptions' - VIEW_VULN_INVESTIGATIONS = 'ViewVulnInvestigations' - MANAGE_VULN_INVESTIGATIONS = 'ManageVulnInvestigations' CREATE_TICKETS = 'CreateTickets' CLOSE_TICKETS = 'CloseTickets' TICKET_ASSIGNEE = 'TicketAssignee' diff --git a/lib/nexpose/version.rb b/lib/nexpose/version.rb index 98d77555..7e5ac867 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.3.2'.freeze + VERSION = '7.3.1'.freeze end From 40bd0370a719c5f453337014adaa9072beeada04 Mon Sep 17 00:00:00 2001 From: Matthew Creighton <85949682+mcreighton-r7@users.noreply.github.com> Date: Thu, 28 Mar 2024 14:36:04 +0000 Subject: [PATCH 56/58] NEX-56926: remove .xml extension on dyntable endpoints (#339) --- lib/nexpose/data_table.rb | 2 +- lib/nexpose/scan.rb | 2 +- lib/nexpose/vuln.rb | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/nexpose/data_table.rb b/lib/nexpose/data_table.rb index 7e325da8..c1067492 100644 --- a/lib/nexpose/data_table.rb +++ b/lib/nexpose/data_table.rb @@ -65,7 +65,7 @@ def _get_json_table(console, address, parameters = {}, page_size = 500, records # @return [Array[Hash]] array of hashes representing the requested table. # # Example usage: - # DataTable._get_dyn_table(@console, '/data/asset/os/dyntable.xml?tableID=OSSynopsisTable') + # DataTable._get_dyn_table(@console, '/data/asset/os/dyntable?tableID=OSSynopsisTable') # def _get_dyn_table(console, address, payload = nil) if payload diff --git a/lib/nexpose/scan.rb b/lib/nexpose/scan.rb index 7650837b..03e48857 100644 --- a/lib/nexpose/scan.rb +++ b/lib/nexpose/scan.rb @@ -396,7 +396,7 @@ def paused_scans(site_id = nil, limit = nil) 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?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 diff --git a/lib/nexpose/vuln.rb b/lib/nexpose/vuln.rb index 8dfb4ca0..3f838a9e 100644 --- a/lib/nexpose/vuln.rb +++ b/lib/nexpose/vuln.rb @@ -35,7 +35,7 @@ def list_vulns(full = false) # @return [Array[String]] Array of currently valid check categories. # def list_vuln_categories - data = DataTable._get_dyn_table(self, '/data/vulnerability/categories/dyntable.xml?tableID=VulnCategorySynopsis') + data = DataTable._get_dyn_table(self, '/data/vulnerability/categories/dyntable?tableID=VulnCategorySynopsis') data.map { |c| c['Category'] } end @@ -46,7 +46,7 @@ def list_vuln_categories # @return [Array[String]] Array of currently valid check types. # def vuln_types - data = DataTable._get_dyn_table(self, '/data/vulnerability/checktypes/dyntable.xml?tableID=VulnCheckCategorySynopsis') + data = DataTable._get_dyn_table(self, '/data/vulnerability/checktypes/dyntable?tableID=VulnCheckCategorySynopsis') data.map { |c| c['Category'] } end alias list_vuln_types vuln_types @@ -74,7 +74,7 @@ def vuln_details(vuln_id) # @return [Array[VulnCheck]] List of matching Vulnerability Checks. # def find_vuln_check(search_term, partial_words = true, all_words = true) - uri = "/data/vulnerability/vulnerabilities/dyntable.xml?tableID=VulnCheckSynopsis&phrase=#{URI.encode(search_term)}&allWords=#{all_words}" + uri = "/data/vulnerability/vulnerabilities/dyntable?tableID=VulnCheckSynopsis&phrase=#{URI.encode(search_term)}&allWords=#{all_words}" data = DataTable._get_dyn_table(self, uri) data.map do |vuln| XML::VulnCheck.new(vuln) @@ -91,7 +91,7 @@ def find_vuln_check(search_term, partial_words = true, all_words = true) # Nexpose between the provided dates. # def find_vulns_by_date(from, to = nil) - uri = "/data/vulnerability/synopsis/dyntable.xml?addedMin=#{from}" + uri = "/data/vulnerability/synopsis/dyntable?addedMin=#{from}" uri += "&addedMax=#{to}" if to DataTable._get_dyn_table(self, uri).map { |v| VulnSynopsis.new(v) } end From 4d5007a89998eb7416791dd4bd1d7610f92a0811 Mon Sep 17 00:00:00 2001 From: phunter-r7 Date: Wed, 7 Aug 2024 20:13:43 +0100 Subject: [PATCH 57/58] Remove mapping for publishedDate --- lib/nexpose/vuln.rb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/nexpose/vuln.rb b/lib/nexpose/vuln.rb index 3f838a9e..560dfcfc 100644 --- a/lib/nexpose/vuln.rb +++ b/lib/nexpose/vuln.rb @@ -153,8 +153,6 @@ class VulnerabilitySummary < Vulnerability attr_accessor :added # The last date the vulnerability was modified. attr_accessor :modified - # The date when the information about the vulnerability was first released. - attr_accessor :published # How the vulnerability is exploited according to PCI standards. attr_accessor :cvss_vector # The computation of the Common Vulnerability Scoring System indicating @@ -173,7 +171,6 @@ def self.parse_attributes(xml) 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 @@ -240,8 +237,6 @@ class VulnFinding attr_reader :cvss_score attr_reader :cvss_vector attr_reader :risk - # Date this vulnerability was published. - attr_reader :published attr_reader :severity # Number of instances of this vulnerabilty finding on an asset. attr_reader :instances @@ -259,7 +254,6 @@ def initialize(json) @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'] @@ -279,7 +273,6 @@ def initialize(hash) @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'] From bcf97c0c1480c6fe6d9c5697ee37d7554c82035b Mon Sep 17 00:00:00 2001 From: dshafranskiy-r7 Date: Thu, 24 Oct 2024 15:59:13 +0200 Subject: [PATCH 58/58] created codeowners and .snyk file --- .snyk | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .snyk diff --git a/.snyk b/.snyk new file mode 100644 index 00000000..ed618909 --- /dev/null +++ b/.snyk @@ -0,0 +1,4 @@ +version: v1.25.0 +ignore: {} +patch: {} +exclude: {}