excl_site_asset_scan 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '../lib/extended-api.rb'))
4
+
5
+ #------------------------------------------------------------------------------------------------------
6
+ # == Synopsis
7
+ # Main script to execute specified API commands against a specified NSC
8
+ #
9
+ # == Usage
10
+ # ruby nexpose_api_util.rb --help
11
+ #
12
+ # == Author
13
+ # Christopher Lee, Rapid7 LLC
14
+ #------------------------------------------------------------------------------------------------------
15
+
16
+ begin
17
+ if ARGV.length > 0
18
+ $is_command_line = false
19
+ begin
20
+ options = Options.parse ARGV
21
+ extended_api = ::ExtendedAPI.new options.user, options.password, options.host
22
+ extended_api.do_login
23
+ case options.key
24
+ when 1 then
25
+ extended_api.print_asset_groups
26
+ when 2 then
27
+ extended_api.print_asset_group_info options.args
28
+ when 3 then
29
+ extended_api.start_excluded_scan options.args
30
+ else
31
+ puts "Invalid Input!"
32
+ end
33
+
34
+ rescue Exception => e
35
+ puts e
36
+ ensure
37
+ begin
38
+ if extended_api
39
+ extended_api.do_logout
40
+ end
41
+ rescue Nexpose::APIError => e
42
+ # Don't care, maybe session already dead
43
+ end
44
+ end
45
+ exit 0
46
+ else
47
+ puts 'Input required'
48
+ end
49
+ end
50
+
51
+
@@ -0,0 +1,41 @@
1
+ require 'ostruct'
2
+ require 'optparse'
3
+
4
+ #------------------------------------------------------------------------------------------------------
5
+ # Defines options to be executed against the NeXpose API
6
+ #------------------------------------------------------------------------------------------------------
7
+ class Options
8
+ def self.parse(args)
9
+ options = OpenStruct.new
10
+ options.verbose = false
11
+
12
+ option_parser = OptionParser.new do |option_parser|
13
+ option_parser.on("-h HOST", "The network address of the NeXpose instance - Required") {|arg| options.host=arg}
14
+ option_parser.on("-u USER", "The user name - Required") {|arg| options.user=arg}
15
+ option_parser.on("-p PASSWORD", "The password - Required") {|arg| options.password=arg}
16
+ option_parser.on("--n1", "List all the asset groups") {|arg| options.key=1}
17
+ option_parser.on("--n2 GI", "List an asset groups config. The GI (group id or group name is required)") do |arg|
18
+ options.key=2
19
+ options.args=arg
20
+ end
21
+ option_parser.on("--ses params", "Start an asset group excluded scan where params are a comma separated list of the site-id to scan followed by
22
+ asset group id(s) to exclude") do |arg|
23
+ options.key=3
24
+ options.args=arg.chomp
25
+ end
26
+ option_parser.on_tail("--help", "Help") do
27
+ puts option_parser
28
+ exit 0
29
+ end
30
+ end
31
+
32
+ begin
33
+ option_parser.parse!(args)
34
+ rescue OptionParser::ParseError => e
35
+ puts "#{e}\n\n#{option_parser}"
36
+ exit 1
37
+ end
38
+
39
+ options
40
+ end
41
+ end
@@ -0,0 +1,117 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'util.rb'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), 'api-options.rb'))
3
+ require 'rubygems'
4
+ require 'rexml/document'
5
+ require 'hirb'
6
+ require 'nexpose'
7
+
8
+ #------------------------------------------------------------------------------------------------------
9
+ # Extends the base API functionality by combining common API commands to produce a simplified
10
+ # user command.
11
+ #------------------------------------------------------------------------------------------------------
12
+ class ExtendedAPI
13
+ attr_accessor :user_name, :password, :host, :nexpose_api, :scan_manager
14
+ @@connected = false
15
+
16
+ def initialize user_name, password, host
17
+ @user_name = user_name
18
+ @password = password
19
+ @host = host
20
+ @nexpose_api = Nexpose::Connection.new @host, @user_name, @password
21
+ end
22
+
23
+ #-------------------------------------------------------------------
24
+ # Logs in to NeXpose and sets a session key on the connector object.
25
+ #-------------------------------------------------------------------
26
+ def do_login
27
+ if not @@connected
28
+ begin
29
+ if @nexpose_api.login
30
+ @@connected = true
31
+ end
32
+ rescue Exception => e
33
+ puts e.message
34
+ end
35
+ end
36
+ end
37
+
38
+ #------------------------------------------------------
39
+ # Prints all asset group information in tabular format:
40
+ # | site_id | device_id | address | riskfactor |
41
+ #------------------------------------------------------
42
+ def print_asset_group_info group_id
43
+ group_configs = @nexpose_api.asset_group_config group_id
44
+ puts "\nASSET GROUP INFO (id: #{group_id})"
45
+ puts Hirb::Helpers::AutoTable.render group_configs, :fields => [:site_id, :device_id, :address, :riskfactor]
46
+ rescue Exception => e
47
+ if e.message =~ /Invalid groupID/
48
+ puts 'Group ID does not exist'
49
+ else
50
+ puts e.message
51
+ end
52
+ end
53
+
54
+ #----------------------------------------------------------------
55
+ # Prints asset group configuration information in tabular format:
56
+ # | site_id | device_id | address | riskfactor |
57
+ #----------------------------------------------------------------
58
+ def print_asset_groups
59
+ res = @nexpose_api.asset_groups_listing
60
+ puts "\nASSET GROUPS:"
61
+ puts Hirb::Helpers::AutoTable.render res, :fields => [:asset_group_id, :name, :description, :risk_score]
62
+ end
63
+
64
+ #
65
+ #
66
+ #
67
+ def start_excluded_scan scan_info
68
+ # Parse the scan_info object to get site
69
+ # to be scanned and the asset group(s) to exclude
70
+ parsed_string = scan_info.to_s.split ','
71
+ site_id = parsed_string[0]
72
+ unless Util.is_number? site_id
73
+ raise ArgumentError.new 'The site-id must be a number'
74
+ end
75
+
76
+ # Get all the device_ids for the site
77
+ device_listing_hash = @nexpose_api.site_device_listing site_id
78
+ device_ids = []
79
+ device_listing_hash.each do |device_listing|
80
+ device_ids << device_listing[:device_id].to_i
81
+ end
82
+
83
+ # Get all the devices associated with the group(s)
84
+ device_ids_excluded = []
85
+ parsed_string.delete_at(0)
86
+ parsed_string.each do |group_id|
87
+ group_infos = @nexpose_api.asset_group_config group_id
88
+ group_infos.each do |group_info|
89
+ device_ids_excluded << group_info[:device_id].to_i
90
+ end
91
+ end
92
+
93
+ # Remove all the devices in the group
94
+ devices_to_scan = device_ids - device_ids_excluded
95
+
96
+ # Hopefully this is not an empty set
97
+ if not devices_to_scan or devices_to_scan.empty?
98
+ raise "There are no devices left to scan after devices in groups: #{parsed_string.inspect} are removed from site: #{site_id}"
99
+ end
100
+
101
+ # Start an ad-hoc scan.
102
+ res = @nexpose_api.site_device_scan_start site_id, devices_to_scan, nil
103
+ if res
104
+ puts "Scan started scan ID: #{res[:scan_id]}, on engine ID: #{res[:engine_id]}"
105
+ else
106
+ put "Scan start failed for site #{site}"
107
+ end
108
+ end
109
+
110
+ #
111
+ #
112
+ #
113
+ def do_logout
114
+ @nexpose_api.logout
115
+ end
116
+
117
+ end
@@ -0,0 +1,33 @@
1
+ class Util
2
+
3
+ #------------------------------------------------------------------------------------------------------
4
+ # Checks if the input is a number
5
+ #
6
+ # input: The object that will be tested
7
+ #------------------------------------------------------------------------------------------------------
8
+ def self.is_number? input
9
+ true if Float input rescue false
10
+ end
11
+
12
+ #------------------------------------------------------------------------------------------------------
13
+ # Retrieves numeric input only from the command line
14
+ #
15
+ # mssg: The message to display that requests the input
16
+ #------------------------------------------------------------------------------------------------------
17
+ def self.get_numeric_input mssg
18
+ begin
19
+ while true
20
+ print mssg
21
+ input = gets().chomp()
22
+ if Util.is_number? input
23
+ return input.to_i
24
+ else
25
+ puts "Input is not a number"
26
+ end
27
+ end
28
+ rescue Exception => e
29
+ puts e.message
30
+ end
31
+ end
32
+
33
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: excl_site_asset_scan
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Christopher Lee
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-07-20 00:00:00.000000000 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: nexpose
17
+ requirement: &23552100 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.3
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *23552100
26
+ - !ruby/object:Gem::Dependency
27
+ name: hirb
28
+ requirement: &23551800 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.4.5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *23551800
37
+ description: ! " \tList asset groups, list information about certain asset groups,
38
+ start a site scan with certain asset groups excluded.\n"
39
+ email: christopher_lee@rapid7.com
40
+ executables:
41
+ - nexpose_api_util
42
+ extensions: []
43
+ extra_rdoc_files: []
44
+ files:
45
+ - lib/api-options.rb
46
+ - lib/extended-api.rb
47
+ - lib/util.rb
48
+ - bin/nexpose_api_util
49
+ has_rdoc: true
50
+ homepage: https://github.com/chrlee/NeXpose-ScanManager-Interface/tree/master/examples/excluded_asset_scan
51
+ licenses: []
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 1.5.2
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: List asset groups, list information about certain asset groups, start a site
74
+ scan with certain asset groups excluded.
75
+ test_files: []