Class: Boris::Target
Overview
Target is the basic class from which you can control the underlying framework for communicating with the device you wish to scan. A Target will allow you to provide options via Options, detect which profiler to use, connect to, and eventually scan your target device, returning a large amount of data.
Instance Attribute Summary collapse
-
#connection_failures ⇒ Object
readonly
Returns the value of attribute connection_failures.
-
#connector ⇒ Object
Returns the value of attribute connector.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#options ⇒ Object
Returns the value of attribute options.
-
#profiler ⇒ Object
Returns the value of attribute profiler.
-
#unavailable_connection_types ⇒ Object
readonly
Returns the value of attribute unavailable_connection_types.
Attributes included from Lumberjack
Instance Method Summary collapse
-
#[](category) ⇒ Array, Hash
Convience method for returning data already collected (internally looks at the Profiler object of Target).
-
#connect ⇒ Boolean
Connects to the target using the credentials supplied via the connection type as specified by the credential.
-
#connected? ⇒ Boolean
Checks on the status of the connection.
-
#detect_profiler ⇒ Module
Cycles through all of the profilers as specified in Options for this target.
-
#disconnect ⇒ Boolean
Gracefully disconnects from the target (if a connection exists).
-
#force_profiler_to(profiler) ⇒ Object
Allows us to force the use of a profiler.
-
#get(category) ⇒ Array, Hash
Convience method for collecting data from a Target, where the user can pass in a symbol for the category that should be collected.
-
#initialize(host, options = {}) ⇒ Target
constructor
Create the target by passing in a mandatory hostname or IP address, and optional options hash.
-
#retrieve_all ⇒ Object
Calls all data-collecting methods.
-
#to_json(print_type = :standard) ⇒ JSON
Parses the target’s scanned data into JSON format for portability.
Methods included from Lumberjack
#debug, #error, #fatal, #info, #warn
Constructor Details
#initialize(host, options = {}) ⇒ Target
Create the target by passing in a mandatory hostname or IP address, and optional options hash.
When a block is passed, the Boris::Target object itself is returned, and the connection will be automatically disconnected at the end of the block (if it exists).
require 'boris'
target = Boris::Target.new('192.168.1.1', :auto_scrub_data=>false)
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/boris/target.rb', line 48 def initialize(host, ={}) @logger = Boris.logger @host = host ||= {} = Options.new() @connector = Connector.new(@host) @connection_failures = [] @unavailable_connection_types = [] if block_given? yield self disconnect if @connector.connected? end end |
Instance Attribute Details
#connection_failures ⇒ Object (readonly)
Returns the value of attribute connection_failures.
27 28 29 |
# File 'lib/boris/target.rb', line 27 def connection_failures @connection_failures end |
#connector ⇒ Object
Returns the value of attribute connector.
31 32 33 |
# File 'lib/boris/target.rb', line 31 def connector @connector end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
28 29 30 |
# File 'lib/boris/target.rb', line 28 def host @host end |
#options ⇒ Object
Returns the value of attribute options.
33 34 35 |
# File 'lib/boris/target.rb', line 33 def end |
#profiler ⇒ Object
Returns the value of attribute profiler.
32 33 34 |
# File 'lib/boris/target.rb', line 32 def profiler @profiler end |
#unavailable_connection_types ⇒ Object (readonly)
Returns the value of attribute unavailable_connection_types.
29 30 31 |
# File 'lib/boris/target.rb', line 29 def unavailable_connection_types @unavailable_connection_types end |
Instance Method Details
#[](category) ⇒ Array, Hash
Convience method for returning data already collected (internally looks at the Profiler object of Target).
target.get(:hardware)
target[:hardware] #=> {:cpu_architecture=>64, :cpu_core_count=>2...}
# same thing as:
target.profiler.hardware #=> {:cpu_architecture=>64, :cpu_core_count=>2...}
78 79 80 |
# File 'lib/boris/target.rb', line 78 def [](category) @profiler.instance_variable_get("@#{category}".to_sym) end |
#connect ⇒ Boolean
Connects to the target using the credentials supplied via the connection type as specified by the credential. This method will smartly bypass any further connection attempts if it is determined that the connection will likely never work (for example, if you try to connect via WMI to a Linux host (which will fail), any further attempts to connect to that host via WMI will be ignored).
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/boris/target.rb', line 91 def connect if @connector.connected? raise ConnectionAlreadyActive, 'a connect attempt has been made when active connection already exists' elsif [:credentials].empty? raise InvalidOption, 'no credentials specified' end debug 'preparing to connect' [:credentials].each do |cred| if @connector.connected? debug 'active connection established, will not try any more credentials' break end debug "using credential (#{cred[:user]})" cred[:connection_types].each do |conn_type| if @connector.connected? debug 'active connection established, will not try any more connection types' break end case conn_type when :snmp @connector = SNMPConnector.new(@host, cred, ) @connector.establish_connection # we won't add snmp to the @unavailable_connection_types array, as it # could respond later with another community string when :ssh if @unavailable_connection_types.include?(:ssh) debug 'connection attempt bypassed (ssh connection unavailable)' else @connector = SSHConnector.new(@host, cred, ) @connector.establish_connection if @connector.reconnectable == false @unavailable_connection_types << :ssh end end when :wmi if @unavailable_connection_types.include?(:wmi) debug 'connection attempt bypassed (wmi connection unavailable)' else @connector = WMIConnector.new(@host, cred) @connector.establish_connection if @connector.reconnectable == false @unavailable_connection_types << :wmi end end end info "connection established via #{conn_type}" if @connector.connected? end @connection_failures = @connection_failures.concat(@connector.) end @connection_failures.uniq! info 'all connection attempts failed' if !@connector.connected? return @connector.connected? ? true : false end |
#connected? ⇒ Boolean
Checks on the status of the connection.
160 161 162 |
# File 'lib/boris/target.rb', line 160 def connected? @connector.connected? end |
#detect_profiler ⇒ Module
Cycles through all of the profilers as specified in Options for this target. Each profiler includes a method for determining whether the output of a certain command will properly fit the target. Once a suitable profiler is determined, it is then loaded up, which provides Boris the instructions on how to proceed.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/boris/target.rb', line 177 def detect_profiler raise InvalidOption, 'no profilers loaded' if [:profilers].empty? || [:profilers].nil? raise NoActiveConnection, 'no active connection' if @connector.connected? == false [:profilers].each do |profiler| break if @profiler || @connector..any? if profiler.connection_type == @connector.class debug "testing profiler: #{profiler}" if profiler.matches_target?(@connector) @profiler = profiler debug "suitable profiler found (#{profiler})" @profiler = @profiler.new(@connector) debug "profiler set to #{profiler}" end end end raise NoProfilerDetected, 'no suitable profiler found' if !@profiler @profiler end |
#disconnect ⇒ Boolean
Gracefully disconnects from the target (if a connection exists).
207 208 209 |
# File 'lib/boris/target.rb', line 207 def disconnect @connector.disconnect if @connector.connected? end |
#force_profiler_to(profiler) ⇒ Object
Allows us to force the use of a profiler. This can be used instead of #detect_profiler.
214 215 216 217 |
# File 'lib/boris/target.rb', line 214 def force_profiler_to(profiler) @profiler = profiler.new(@connector) debug "profiler successfully forced to #{profiler}" end |
#get(category) ⇒ Array, Hash
Convience method for collecting data from a Target, where the user can pass in a symbol for the category that should be collected.
target.get(:hardware) #=> {:cpu_architecture=>64, :cpu_core_count=>2...}
# same thing as:
target.profiler.get_hardware #=> {:cpu_architecture=>64, :cpu_core_count=>2...}
230 231 232 233 |
# File 'lib/boris/target.rb', line 230 def get(category) @profiler.send("get_#{category.to_s}") self[category] end |
#retrieve_all ⇒ Object
Running the full gamut of data collection methods may take some time, and connections over WMI usually take longer than their SSH counterparts. Typically, a Linux server scan can be completed in just a minute or two, whereas a Windows host will be completed in 2-3 minutes (there are many other factors, of course).
Calls all data-collecting methods. Probably will be used in most cases after a connection has been established to the host. Methods that will be called include:
-
get_file_systems (Array)
-
get_hardware (Hash)
-
get_hosted_shares (Array)
-
get_installed_applications (Array)
-
get_local_user_groups (Array)
-
get_installed_patches (Array)
-
get_installed_services (Array)
-
get_network_id (Hash)
-
get_network_interfaces (Array)
-
get_operating_system (Hash)
target.retrieve_all
target[:file_systems].size #=> 2
target[:installed_applications].first #=> {:application_name=>'Adobe Reader'...}
This method will also scrub the data after retrieving all of the items (unless the
:auto_scrub option is set to false).
260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/boris/target.rb', line 260 def retrieve_all raise NoActiveConnection, 'no active connection' if @connector.connected? == false debug 'retrieving all configuration items' Structure::CATEGORIES.each do |category| debug "calling #get_#{category.to_s}" @profiler.send("get_#{category.to_s}") end debug 'all items retrieved successfully' @profiler.scrub_data! if [:auto_scrub_data] end |
#to_json(print_type = :standard) ⇒ JSON
Parses the target’s scanned data into JSON format for portability.
target.get(:network_id)
json_string = target.to_json #=> "...{\"domain\":\"mydomain.com\",\"hostname\":\"SERVER01\"}"...
284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/boris/target.rb', line 284 def to_json(print_type=:standard) json = {} Structure::CATEGORIES.each do |category| json[category.to_sym] = @profiler.instance_variable_get("@#{category}".to_sym) end generated_json = print_type == :pretty_print ? JSON.pretty_generate(json) : JSON.generate(json) debug "json generated successfully" generated_json end |