class Nexpose::Site

Configuration object representing a Nexpose site.

For a basic walk-through, see {github.com/rapid7/nexpose-client/wiki/Using-Sites}

Attributes

alerts[RW]
Array

Collection of real-time alerts.

@see Alert @see SMTPAlert @see SNMPAlert @see SyslogAlert

auto_engine_selection_enabled[RW]

Scan the assets with last scanned engine or not.

blackouts[RW]
Array

Blackout starting dates, times and duration for blackout periods.

config_version[RW]

Configuration version. Default: 3

description[RW]

Description of the site.

discovery_config[RW]

discovery config of the discovery connection associated with this site if it is dynamic.

engine_id[RW]

Scan Engine to use. Will use the default engine if nil or -1.

excluded_scan_targets[RW]

Excluded scan targets. May be IPv4, IPv6, DNS names, IPRanges or assetgroup ids.

id[RW]

The site ID. An ID of -1 is used to designate a site that has not been saved to a Nexpose console.

included_scan_targets[RW]

Included scan targets. May be IPv4, IPv6, DNS names, IPRanges or assetgroup ids.

name[RW]

Unique name of the site. Required.

organization[RW]

Information about the organization that this site belongs to. Used by some reports.

risk_factor[RW]

The risk factor associated with this site. Default: 1.0

scan_template_id[RW]

Scan template to use when starting a scan job. Default: full-audit-without-web-spider

scan_template_name[RW]

Friendly name of scan template to use when starting a scan job. Value is populated when a site is saved or loaded from a console.

schedules[RW]
Array

Schedule starting dates and times for scans, and set their frequency.

search_criteria[RW]

Asset filter criteria if this site is dynamic.

shared_credentials[RW]
Array

Collection of shared credentials associated with this site.

site_credentials[RW]
Array

Collection of credentials associated with this site. Does not

include shared credentials.

tags[RW]
Array

Collection of TagSummary

users[RW]
Array

List of user IDs for users who have access to the site.

web_credentials[RW]
Array

Collection of web credentials associated with the site.

Public Class Methods

copy(connection, id) click to toggle source

Copy an existing configuration from a Nexpose instance. Returned object will reset the site ID and append “Copy” to the existing name.

@param [Connection] connection Connection to the security console. @param [Fixnum] id Site ID of an existing site. @return [Site] Site configuration loaded from a Nexpose console.

# File lib/nexpose/site.rb, line 496
def self.copy(connection, id)
  site      = self.load(connection, id)
  site.id   = -1
  site.name = "#{site.name} Copy"
  site
end
from_hash(hash) click to toggle source
# File lib/nexpose/site.rb, line 390
def self.from_hash(hash)
  site = new(hash[:name], hash[:scan_template_id])
  hash.each do |k, v|
    site.instance_variable_set("@#{k}", v)
  end

  # Convert each string address to either a HostName or IPRange object
  included_scan_targets = { addresses: [], asset_groups: [] }
  site.included_scan_targets[:addresses].each { |asset| included_scan_targets[:addresses] << HostOrIP.convert(asset) }
  included_scan_targets[:asset_groups] = site.included_scan_targets[:asset_groups]
  site.included_scan_targets = included_scan_targets

  excluded_scan_targets = { addresses: [], asset_groups: [] }
  site.excluded_scan_targets[:addresses].each { |asset| excluded_scan_targets[:addresses] << HostOrIP.convert(asset) }
  excluded_scan_targets[:asset_groups] = site.excluded_scan_targets[:asset_groups]
  site.excluded_scan_targets = excluded_scan_targets

  site
end
json_initializer(data) click to toggle source
# File lib/nexpose/site.rb, line 484
def self.json_initializer(data)
  new(data[:name], data[:scan_template_id])
end
load(nsc, id) click to toggle source

Load an site from the provided console.

@param [Connection] nsc Active connection to a Nexpose console. @param [String] id Unique identifier of a site. @return [Site] The requested site, if found.

# File lib/nexpose/site.rb, line 452
def self.load(nsc, id)
  uri  = "/api/2.1/site_configurations/#{id}"
  resp = AJAX.get(nsc, uri, AJAX::CONTENT_TYPE::JSON)
  hash = JSON.parse(resp, symbolize_names: true)
  site = self.json_initializer(hash).deserialize(hash)

  # Convert each string address to either a HostName or IPRange object
  included_addresses = hash[:included_scan_targets][:addresses]
  site.included_scan_targets[:addresses] = []
  included_addresses.each { |asset| site.include_asset(asset) }

  excluded_addresses = hash[:excluded_scan_targets][:addresses]
  site.excluded_scan_targets[:addresses] = []
  excluded_addresses.each { |asset| site.exclude_asset(asset) }

  site.organization       = Organization.create(site.organization)
  site.schedules          = (hash[:schedules] || []).map { |schedule| Nexpose::Schedule.from_hash(schedule) }
  site.blackouts          = (hash[:blackouts] || []).map { |blackout| Nexpose::Blackout.from_hash(blackout) }
  site.site_credentials   = hash[:site_credentials].map { |cred| Nexpose::SiteCredentials.new.object_from_hash(nsc, cred) }
  site.shared_credentials = hash[:shared_credentials].map { |cred| Nexpose::SiteCredentials.new.object_from_hash(nsc, cred) }
  site.discovery_config   = Nexpose::DiscoveryConnection.new.object_from_hash(nsc, hash[:discovery_config]) unless hash[:discovery_config].nil?
  site.search_criteria    = Nexpose::DiscoveryConnection::Criteria.parseHash(hash[:search_criteria]) unless hash[:search_criteria].nil?
  site.alerts             = Alert.load_alerts(hash[:alerts])
  site.tags               = Tag.load_tags(hash[:tags])
  site.web_credentials = hash[:web_credentials].map { |web_cred| (
  web_cred[:service] == Nexpose::WebCredentials::WebAppAuthType::HTTP_HEADER ?
      Nexpose::WebCredentials::Headers.new(web_cred[:name], web_cred[:baseURL], web_cred[:soft403Pattern], web_cred[:id]).object_from_hash(nsc, web_cred) :
      Nexpose::WebCredentials::HTMLForms.new(web_cred[:name], web_cred[:baseURL], web_cred[:loginURL], web_cred[:soft403Pattern], web_cred[:id]).object_from_hash(nsc, web_cred)) }

  site
end
new(name = nil, scan_template_id = 'full-audit-without-web-spider') click to toggle source

Site constructor. Both arguments are optional.

@param [String] name Unique name of the site. @param [String] scan_template_id ID of the scan template to use.

# File lib/nexpose/site.rb, line 160
def initialize(name = nil, scan_template_id = 'full-audit-without-web-spider')
  @name                  = name
  @scan_template_id      = scan_template_id
  @id                    = -1
  @risk_factor           = 1.0
  @config_version        = 3
  @schedules             = []
  @blackouts             = []
  @included_scan_targets = { addresses: [], asset_groups: [] }
  @excluded_scan_targets = { addresses: [], asset_groups: [] }
  @site_credentials      = []
  @shared_credentials    = []
  @web_credentials       = []
  @alerts                = []
  @users                 = []
  @tags                  = []
end

Public Instance Methods

add_user(user_id) click to toggle source
# File lib/nexpose/site.rb, line 374
def add_user(user_id)
  unless user_id.is_a?(Numeric) && user_id > 0
    raise 'Invalid user id. A user id must be a positive number and refer to an existing system user.'
  end

  @users << { id: user_id }
end
delete(connection) click to toggle source

Delete this site from a Nexpose console.

@param [Connection] connection Connection to console where this site will be saved. @return [Boolean] Whether or not the site was successfully deleted.

# File lib/nexpose/site.rb, line 534
def delete(connection)
  r = connection.execute(%(<SiteDeleteRequest session-id="#{connection.session_id}" site-id="#{@id}"/>))
  r.success
end
dynamic?()
Alias for: is_dynamic?
exclude_asset(asset) click to toggle source

Adds an asset to this site excluded scan targets, resolving whether an IP or hostname is provided.

@param [String] asset Identifier of an asset, either IP or host name.

# File lib/nexpose/site.rb, line 315
def exclude_asset(asset)
  @excluded_scan_targets[:addresses] << HostOrIP.convert(asset)
end
exclude_asset_group(asset_group_id) click to toggle source

Adds an asset group ID to this site excluded scan targets.

@param [Integer] asset_group_id Identifier of an assetGroupID.

# File lib/nexpose/site.rb, line 350
def exclude_asset_group(asset_group_id)
  validate_asset_group(asset_group_id)
  @excluded_scan_targets[:asset_groups] << asset_group_id.to_i
end
exclude_ip_range(from, to) click to toggle source

Adds assets to this site excluded scan targets by IP address range.

@param [String] from Beginning IP address of a range. @param [String] to Ending IP address of a range.

# File lib/nexpose/site.rb, line 286
def exclude_ip_range(from, to)
  from_ip = IPAddr.new(from)
  to_ip   = IPAddr.new(to)
  (from_ip..to_ip)
  raise 'Invalid IP range specified' if (from_ip..to_ip).to_a.size.zero?
  @excluded_scan_targets[:addresses] << IPRange.new(from, to)
rescue ArgumentError => e
  raise "#{e.message} in given IP range"
end
excluded_addresses() click to toggle source

Returns the array of excluded scan target addresses. @return [Array] Array of excluded addresses.

# File lib/nexpose/site.rb, line 206
def excluded_addresses
  @excluded_scan_targets[:addresses]
end
excluded_addresses=(new_addresses) click to toggle source

Sets the array of excluded scan target addresses. @param [Array] new_addresses The new array of scan target addresses. @return [Array] Array of updated scan target addresses.

# File lib/nexpose/site.rb, line 213
def excluded_addresses=(new_addresses)
  @excluded_scan_targets[:addresses] = new_addresses
end
excluded_asset_groups() click to toggle source

Returns the array of IDs for excluded scan target asset groups. @return [Array] Array of IDs for excluded asset groups.

# File lib/nexpose/site.rb, line 219
def excluded_asset_groups
  @excluded_scan_targets[:asset_groups]
end
excluded_asset_groups=(new_asset_groups) click to toggle source

Sets the array IDs for excluded scan target asset groups. @param [Array] new_asset_groups The new array of IDs for scan target asset groups. @return [Array] Array of IDs of the updated scan target asset groups.

# File lib/nexpose/site.rb, line 226
def excluded_asset_groups=(new_asset_groups)
  @excluded_scan_targets[:asset_groups] = new_asset_groups
end
include_asset(asset) click to toggle source

Adds an asset to this site included scan targets, resolving whether an IP or hostname is provided.

@param [String] asset Identifier of an asset, either IP or host name.

# File lib/nexpose/site.rb, line 269
def include_asset(asset)
  @included_scan_targets[:addresses] << HostOrIP.convert(asset)
end
include_asset_group(asset_group_id) click to toggle source

Adds an asset group ID to this site included scan targets.

@param [Integer] asset_group_id Identifier of an assetGroupID.

# File lib/nexpose/site.rb, line 332
def include_asset_group(asset_group_id)
  validate_asset_group(asset_group_id)
  @included_scan_targets[:asset_groups] << asset_group_id.to_i
end
include_ip_range(from, to) click to toggle source

Adds assets to this site by IP address range.

@param [String] from Beginning IP address of a range. @param [String] to Ending IP address of a range.

# File lib/nexpose/site.rb, line 240
def include_ip_range(from, to)
  from_ip = IPAddr.new(from)
  to_ip   = IPAddr.new(to)
  (from_ip..to_ip)
  raise 'Invalid IP range specified' if (from_ip..to_ip).to_a.size.zero?
  @included_scan_targets[:addresses] << IPRange.new(from, to)
rescue ArgumentError => e
  raise "#{e.message} in given IP range"
end
included_addresses() click to toggle source

Returns the array of included scan target addresses. @return [Array] Array of included addresses.

# File lib/nexpose/site.rb, line 180
def included_addresses
  @included_scan_targets[:addresses]
end
included_addresses=(new_addresses) click to toggle source

Sets the array of included scan target addresses. @param [Array] new_addresses The new array of scan target addresses. @return [Array] Array of updated scan target addresses.

# File lib/nexpose/site.rb, line 187
def included_addresses=(new_addresses)
  @included_scan_targets[:addresses] = new_addresses
end
included_asset_groups() click to toggle source

Returns the array of IDs for included scan target asset groups. @return [Array] Array of included asset groups.

# File lib/nexpose/site.rb, line 193
def included_asset_groups
  @included_scan_targets[:asset_groups]
end
included_asset_groups=(new_asset_groups) click to toggle source

Sets the array of IDs for included scan target asset groups. @param [Array new_asset_groups The new array of IDs for scan target asset groups. @return [Array Array of IDs of the updated scan target asset groups.

# File lib/nexpose/site.rb, line 200
def included_asset_groups=(new_asset_groups)
  @included_scan_targets[:asset_groups] = new_asset_groups
end
is_dynamic?() click to toggle source

Returns true when the site is dynamic.

# File lib/nexpose/site.rb, line 231
def is_dynamic?
  !@discovery_config.nil?
end
Also aliased as: dynamic?
remove_excluded_asset(asset) click to toggle source

Removes an asset to this site excluded scan targets, resolving whether an IP or hostname is provided.

@param [String] asset Identifier of an asset, either IP or host name.

# File lib/nexpose/site.rb, line 324
def remove_excluded_asset(asset)
  @excluded_scan_targets[:addresses].reject! { |existing_asset| existing_asset == HostOrIP.convert(asset) }
end
remove_excluded_asset_group(asset_group_id) click to toggle source

Adds an asset group ID to this site excluded scan targets.

@param [Integer] asset_group_id Identifier of an assetGroupID.

# File lib/nexpose/site.rb, line 359
def remove_excluded_asset_group(asset_group_id)
  validate_asset_group(asset_group_id)
  @excluded_scan_targets[:asset_groups].reject! { |t| t.eql? asset_group_id.to_i }
end
remove_excluded_ip_range(from, to) click to toggle source

Remove assets from this site excluded scan targets by IP address range.

@param [String] from Beginning IP address of a range. @param [String] to Ending IP address of a range.

# File lib/nexpose/site.rb, line 300
def remove_excluded_ip_range(from, to)
  from_ip = IPAddr.new(from)
  to_ip   = IPAddr.new(to)
  (from_ip..to_ip)
  raise 'Invalid IP range specified' if (from_ip..to_ip).to_a.size.zero?
  @excluded_scan_targets[:addresses].reject! { |t| t.eql? IPRange.new(from, to) }
rescue ArgumentError => e
  raise "#{e.message} in given IP range"
end
remove_included_asset(asset) click to toggle source

Remove an asset to this site included scan targets, resolving whether an IP or hostname is provided.

@param [String] asset Identifier of an asset, either IP or host name.

# File lib/nexpose/site.rb, line 278
def remove_included_asset(asset)
  @included_scan_targets[:addresses].reject! { |existing_asset| existing_asset == HostOrIP.convert(asset) }
end
remove_included_asset_group(asset_group_id) click to toggle source

Adds an asset group ID to this site included scan targets.

@param [Integer] asset_group_id Identifier of an assetGroupID.

# File lib/nexpose/site.rb, line 341
def remove_included_asset_group(asset_group_id)
  validate_asset_group(asset_group_id)
  @included_scan_targets[:asset_groups].reject! { |t| t.eql? asset_group_id.to_i }
end
remove_included_ip_range(from, to) click to toggle source

Remove assets to this site by IP address range.

@param [String] from Beginning IP address of a range. @param [String] to Ending IP address of a range.

# File lib/nexpose/site.rb, line 254
def remove_included_ip_range(from, to)
  from_ip = IPAddr.new(from)
  to_ip   = IPAddr.new(to)
  (from_ip..to_ip)
  raise 'Invalid IP range specified' if (from_ip..to_ip).to_a.size.zero?
  @included_scan_targets[:addresses].reject! { |t| t.eql? IPRange.new(from, to) }
rescue ArgumentError => e
  raise "#{e.message} in given IP range"
end
remove_user(user_id) click to toggle source
# File lib/nexpose/site.rb, line 382
def remove_user(user_id)
  unless user_id.is_a?(Numeric) && user_id > 0
    raise 'Invalid user id. A user id must be a positive number and refer to an existing system user.'
  end

  @users.delete_if { |h| h[:id] == user_id }
end
save(connection) click to toggle source

Saves this site to a Nexpose console. If the site is dynamic, connection and asset filter changes must be saved through the DiscoveryConnection#update_site call.

@param [Connection] connection Connection to console where this site will be saved. @return [Fixnum] Site ID assigned to this configuration, if successful.

# File lib/nexpose/site.rb, line 510
def save(connection)
  new_site = @id == -1

  if new_site
    resp = AJAX.post(connection, '/api/2.1/site_configurations/', to_json, AJAX::CONTENT_TYPE::JSON)
    @id = resp.to_i
  else
    AJAX.put(connection, "/api/2.1/site_configurations/#{@id}", to_json, AJAX::CONTENT_TYPE::JSON)
  end

  # Retrieve the scan engine and shared credentials and add them to the site configuration
  site_config         = Site.load(connection, @id)
  @engine_id          = site_config.engine_id
  @shared_credentials = site_config.shared_credentials
  @alerts             = site_config.alerts

  @id
end
scan(connection, sync_id = nil, blackout_override = false) click to toggle source

Scan this site.

@param [Connection] connection Connection to console where scan will be launched. @param [String] sync_id Optional synchronization token. @param [Boolean] blackout_override Optional. Given suffencent permissions, force bypass blackout and start scan. @return [Scan] Scan launch information.

# File lib/nexpose/site.rb, line 546
def scan(connection, sync_id = nil, blackout_override = false)
  xml = REXML::Element.new('SiteScanRequest')
  xml.add_attributes({ 'session-id' => connection.session_id,
                       'site-id' => @id,
                       'sync-id' => sync_id })

  xml.add_attributes({ 'force' => true }) if blackout_override
  response = connection.execute(xml, '1.1', timeout: connection.timeout)
  Scan.parse(response.res) if response.success
end
to_h() click to toggle source
# File lib/nexpose/site.rb, line 414
def to_h
  included_scan_targets = { addresses: @included_scan_targets[:addresses].compact,
                            asset_groups: @included_scan_targets[:asset_groups].compact }
  excluded_scan_targets = { addresses: @excluded_scan_targets[:addresses].compact,
                            asset_groups: @excluded_scan_targets[:asset_groups].compact }
  hash = { id: @id,
           name: @name,
           description: @description,
           auto_engine_selection_enabled: @auto_engine_selection_enabled,
           included_scan_targets: included_scan_targets,
           excluded_scan_targets: excluded_scan_targets,
           engine_id: @engine_id,
           scan_template_id: @scan_template_id,
           risk_factor: @risk_factor,
           schedules: (@schedules || []).map(&:to_h),
           shared_credentials: (@shared_credentials || []).map(&:to_h),
           site_credentials: (@site_credentials || []).map(&:to_h),
           web_credentials: (@web_credentials || []).map(&:to_h),
           discovery_config: @discovery_config.to_h,
           search_criteria: @search_criteria.to_h,
           tags: (@tags || []).map(&:to_h),
           alerts: (@alerts || []).map(&:to_h),
           organization: @organization.to_h,
           users: users }
  # @TODO: Revisit this for 2.0.0 update
  # Only pass in blackouts if they were actually specified (for backwards compatibility)
  hash[:blackouts] = @blackouts.map(&:to_h) if @blackouts && @blackouts.any?

  hash
end
to_json() click to toggle source
# File lib/nexpose/site.rb, line 410
def to_json
  JSON.generate(to_h)
end
validate_asset_group(asset_group_id) click to toggle source
# File lib/nexpose/site.rb, line 364
def validate_asset_group(asset_group_id)
  begin
    Integer(asset_group_id)
  rescue ArgumentError => e
    raise "Invalid asset_group id. #{e.message}"
  end

  raise 'Invalid asset_group id. Must be positive number.' if asset_group_id.to_i < 1
end