boris 1.0.0.beta.1 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +11 -0
- data/README.md +114 -32
- data/Rakefile +19 -0
- data/lib/boris.rb +0 -13
- data/lib/boris/connectors.rb +25 -7
- data/lib/boris/connectors/snmp.rb +24 -4
- data/lib/boris/connectors/ssh.rb +32 -6
- data/lib/boris/connectors/wmi.rb +109 -54
- data/lib/boris/errors.rb +1 -1
- data/lib/boris/helpers/array.rb +62 -62
- data/lib/boris/helpers/constants.rb +22 -19
- data/lib/boris/helpers/hash.rb +7 -7
- data/lib/boris/helpers/network.rb +68 -0
- data/lib/boris/helpers/scrubber.rb +53 -51
- data/lib/boris/helpers/string.rb +148 -26
- data/lib/boris/lumberjack.rb +74 -47
- data/lib/boris/options.rb +28 -16
- data/lib/boris/profiler.rb +19 -0
- data/lib/boris/profilers/linux/redhat.rb +74 -0
- data/lib/boris/{profiles → profilers}/linux_core.rb +13 -4
- data/lib/boris/{profiles → profilers}/unix/solaris.rb +25 -15
- data/lib/boris/{profiles → profilers}/unix_core.rb +90 -85
- data/lib/boris/profilers/windows/windows2003.rb +11 -0
- data/lib/boris/profilers/windows/windows2008.rb +26 -0
- data/lib/boris/profilers/windows/windows2012.rb +11 -0
- data/lib/boris/{profiles → profilers}/windows_core.rb +36 -14
- data/lib/boris/structure.rb +173 -167
- data/lib/boris/target.rb +110 -168
- data/lib/boris/version.rb +3 -0
- metadata +32 -115
- data/boris.gemspec +0 -28
- data/doc/Array.html +0 -437
- data/doc/Boris.html +0 -230
- data/doc/Boris/ConnectionAlreadyActive.html +0 -123
- data/doc/Boris/ConnectionFailed.html +0 -127
- data/doc/Boris/Connector.html +0 -794
- data/doc/Boris/InvalidCredentials.html +0 -131
- data/doc/Boris/InvalidOption.html +0 -123
- data/doc/Boris/InvalidTargetName.html +0 -123
- data/doc/Boris/Lumberjack.html +0 -466
- data/doc/Boris/MissingCredentials.html +0 -123
- data/doc/Boris/NoActiveConnection.html +0 -123
- data/doc/Boris/NoProfileDetected.html +0 -123
- data/doc/Boris/Options.html +0 -783
- data/doc/Boris/Profiles.html +0 -117
- data/doc/Boris/Profiles/Linux.html +0 -1151
- data/doc/Boris/Profiles/RedHat.html +0 -875
- data/doc/Boris/Profiles/Solaris.html +0 -1230
- data/doc/Boris/Profiles/Structure.html +0 -2050
- data/doc/Boris/Profiles/UNIX.html +0 -893
- data/doc/Boris/Profiles/Windows.html +0 -1846
- data/doc/Boris/Profiles/Windows/Windows2003.html +0 -304
- data/doc/Boris/Profiles/Windows/Windows2008.html +0 -379
- data/doc/Boris/Profiles/Windows/Windows2012.html +0 -304
- data/doc/Boris/SNMPConnector.html +0 -512
- data/doc/Boris/SSHConnector.html +0 -633
- data/doc/Boris/Target.html +0 -2002
- data/doc/Boris/WMIConnector.html +0 -1134
- data/doc/BorisLogger.html +0 -217
- data/doc/Hash.html +0 -195
- data/doc/String.html +0 -1246
- data/doc/_index.html +0 -420
- data/doc/class_list.html +0 -53
- data/doc/css/common.css +0 -1
- data/doc/css/full_list.css +0 -57
- data/doc/css/style.css +0 -328
- data/doc/file.README.html +0 -183
- data/doc/file_list.html +0 -55
- data/doc/frames.html +0 -28
- data/doc/index.html +0 -183
- data/doc/js/app.js +0 -214
- data/doc/js/full_list.js +0 -173
- data/doc/js/jquery.js +0 -4
- data/doc/method_list.html +0 -1468
- data/doc/top-level-namespace.html +0 -126
- data/lib/boris/profiles/linux/redhat.rb +0 -77
- data/lib/boris/profiles/windows/windows2003.rb +0 -15
- data/lib/boris/profiles/windows/windows2008.rb +0 -23
- data/lib/boris/profiles/windows/windows2012.rb +0 -15
- data/test/connector_tests/test_snmp.rb +0 -35
- data/test/connector_tests/test_ssh.rb +0 -51
- data/test/connector_tests/test_wmi.rb +0 -129
- data/test/helper_tests/test_array.rb +0 -25
- data/test/helper_tests/test_hash.rb +0 -10
- data/test/helper_tests/test_string.rb +0 -136
- data/test/profile_tests/test_core_skeleton +0 -107
- data/test/profile_tests/test_linux_core.rb +0 -331
- data/test/profile_tests/test_redhat.rb +0 -134
- data/test/profile_tests/test_solaris.rb +0 -523
- data/test/profile_tests/test_unix_core.rb +0 -117
- data/test/profile_tests/test_windows.rb +0 -536
- data/test/setup_tests.rb +0 -14
- data/test/test_all.rb +0 -8
- data/test/test_options.rb +0 -44
- data/test/test_structure.rb +0 -136
- data/test/test_target.rb +0 -146
data/lib/boris/connectors/wmi.rb
CHANGED
@@ -8,10 +8,17 @@ module Boris
|
|
8
8
|
KEY_QUERY_VALUE = 1
|
9
9
|
KEY_ENUMERATE_SUB_KEYS = 8
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
# Create an instance of WMIConnector by passing in a mandatory hostname or IP address,
|
12
|
+
# credential to try, and optional Hash of {Boris::Options options}. Under the hood, this
|
13
|
+
# class uses the WIN32OLE library.
|
14
|
+
#
|
15
|
+
# @param [String] host hostname or IP address
|
16
|
+
# @param [Hash] cred credential we wish to use
|
17
|
+
def initialize(host, cred)
|
18
|
+
super(host, cred)
|
13
19
|
end
|
14
20
|
|
21
|
+
# Disconnect from the host.
|
15
22
|
def disconnect
|
16
23
|
super
|
17
24
|
@wmi = nil
|
@@ -21,6 +28,9 @@ module Boris
|
|
21
28
|
debug 'connections closed'
|
22
29
|
end
|
23
30
|
|
31
|
+
# Establish our connection. Three connection types are created: one to the WMI cimv2
|
32
|
+
# namespace, one to the WMI root namespace, and one to the registry.
|
33
|
+
# @return [WMIConnector] instance of WMIConnector
|
24
34
|
def establish_connection
|
25
35
|
super
|
26
36
|
|
@@ -62,55 +72,23 @@ module Boris
|
|
62
72
|
info 'connection does not seem to be available (so we will not retry)'
|
63
73
|
end unless @transport
|
64
74
|
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
def value_at(request, conn=:wmi)
|
69
|
-
values_at(request, conn, limit=1)[0]
|
70
|
-
end
|
71
|
-
|
72
|
-
def values_at(request, conn=:wmi, limit=nil)
|
73
|
-
super(request, limit)
|
74
|
-
|
75
|
-
rows = case conn
|
76
|
-
when :root_wmi
|
77
|
-
@root_wmi.ExecQuery(request, nil, 48)
|
78
|
-
when :wmi
|
79
|
-
@wmi.ExecQuery(request, nil, 48)
|
80
|
-
end
|
81
|
-
|
82
|
-
return_data = []
|
83
|
-
|
84
|
-
i = 0
|
85
|
-
|
86
|
-
rows.each do |row|
|
87
|
-
i += 1
|
88
|
-
|
89
|
-
return_hash = {}
|
90
|
-
|
91
|
-
row.Properties_.each do |property|
|
92
|
-
if property.Name =~ /^attributes/i && property.Value.kind_of?(WIN32OLE)
|
93
|
-
row.Attributes.Properties_.each do |property|
|
94
|
-
return_hash[property.Name.downcase.to_sym] = property.Value
|
95
|
-
end
|
96
|
-
else
|
97
|
-
return_hash[property.Name.downcase.to_sym] = property.Value
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
return_data << return_hash
|
102
|
-
|
103
|
-
break if (limit.nil? && i == limit)
|
104
|
-
end
|
105
|
-
|
106
|
-
info "#{return_data.size} row(s) returned"
|
107
|
-
|
108
|
-
return return_data
|
75
|
+
self
|
109
76
|
end
|
110
77
|
|
78
|
+
# Check if we have access to perform an action on the specified key path. This
|
79
|
+
# adds a slight overhead in terms of registry read speed, as internally Boris
|
80
|
+
# will check for access to enumerate subkeys for each registry key it wants to
|
81
|
+
# read, but this does cut down on the number of access errors on the host.
|
82
|
+
#
|
83
|
+
# # KEY_ENUMERATE_SUB_KEYS and KEY_QUERY_VALUE are constants specified in Boris.
|
84
|
+
# # Check Microsoft docs for other possible values.
|
85
|
+
# connector.has_access_for('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', KEY_ENUMERATE_SUB_KEYS)
|
86
|
+
# #=> true
|
87
|
+
#
|
88
|
+
# @param [String] key_path the registry key we wish to check access for
|
89
|
+
# @param [Integer] permission_to_check the access we wish to test
|
90
|
+
# @return [Boolean] true if we have access to perform this action on specified key
|
111
91
|
def has_access_for(key_path, permission_to_check=nil)
|
112
|
-
debug "checking for registry read access for #{key_path}"
|
113
|
-
|
114
92
|
access_params = @registry.Methods_('CheckAccess').inParameters.SpawnInstance_
|
115
93
|
|
116
94
|
access_params.hDefKey = HKEY_LOCAL_MACHINE
|
@@ -120,8 +98,17 @@ module Boris
|
|
120
98
|
@registry.ExecMethod_('CheckAccess', access_params).bGranted
|
121
99
|
end
|
122
100
|
|
101
|
+
|
102
|
+
# Returns an array of subkey names found at the specified key path under
|
103
|
+
# HKEY_LOCAL_MACHINE.
|
104
|
+
#
|
105
|
+
# connector.registry_subkeys_at('SOFTWARE\Microsoft')
|
106
|
+
# #=> ['SOFTWARE\Microsoft\Office', 'SOFTWARE\Microsoft\Windows'...]
|
107
|
+
#
|
108
|
+
# @param [String] key_path the registry key we wish to test
|
109
|
+
# @return [Array] array of subkeys found
|
123
110
|
def registry_subkeys_at(key_path)
|
124
|
-
|
111
|
+
subkeys = []
|
125
112
|
|
126
113
|
debug "reading registry subkeys at path #{key_path}"
|
127
114
|
|
@@ -131,15 +118,23 @@ module Boris
|
|
131
118
|
in_params.sSubKeyName = key_path
|
132
119
|
|
133
120
|
@registry.ExecMethod_('EnumKey', in_params).sNames.each do |key|
|
134
|
-
|
121
|
+
subkeys << key_path + '\\' + key
|
135
122
|
end
|
136
123
|
else
|
137
124
|
info "no access for enumerating keys at (#{key_path})"
|
138
125
|
end
|
139
126
|
|
140
|
-
|
127
|
+
subkeys
|
141
128
|
end
|
142
129
|
|
130
|
+
# Returns an array of values found at the specified key path under
|
131
|
+
# HKEY_LOCAL_MACHINE.
|
132
|
+
#
|
133
|
+
# connector.registry_values_at('SOFTWARE\Microsoft')
|
134
|
+
# #=> {:valuename=>value, ...}
|
135
|
+
#
|
136
|
+
# @param [String] key_path the registry key we wish to test
|
137
|
+
# @return [Hash] hash of key/value pairs found at the specified key path
|
143
138
|
def registry_values_at(key_path)
|
144
139
|
values = Hash.new
|
145
140
|
|
@@ -157,7 +152,7 @@ module Boris
|
|
157
152
|
subkey_values ||= []
|
158
153
|
|
159
154
|
subkey_values.each do |value|
|
160
|
-
if
|
155
|
+
if value.length > 0
|
161
156
|
str_params.sValueName = value
|
162
157
|
|
163
158
|
begin
|
@@ -170,7 +165,7 @@ module Boris
|
|
170
165
|
|
171
166
|
values[value.downcase.to_sym] = x
|
172
167
|
rescue
|
173
|
-
if $!.message =~
|
168
|
+
if $!.message =~ /invalid method/i
|
174
169
|
warn "unreadable registry value (#{key_path}\\#{value})"
|
175
170
|
end
|
176
171
|
end
|
@@ -180,7 +175,67 @@ module Boris
|
|
180
175
|
info "no access for enumerating values at (#{key_path})"
|
181
176
|
end
|
182
177
|
|
183
|
-
|
178
|
+
values
|
184
179
|
end
|
180
|
+
|
181
|
+
# Return a single value from our request.
|
182
|
+
#
|
183
|
+
# @param [String] request the command we wish to execute over this connection
|
184
|
+
# @param [Symbol] conn the channel we should use for our request
|
185
|
+
# Options: +:root_wmi+, +:cimv2+ (default)
|
186
|
+
# @return [String] the first row/line returned by the host
|
187
|
+
def value_at(request, conn=:cimv2)
|
188
|
+
values_at(request, conn, limit=1)[0]
|
189
|
+
end
|
190
|
+
|
191
|
+
# Return multiple values from our request, up to the limit specified (or no
|
192
|
+
# limit if no limit parameter is specified.
|
193
|
+
#
|
194
|
+
# @param [String] request the command we wish to execute over this connection
|
195
|
+
# @param [Symbol] conn the channel we should use for our request
|
196
|
+
# Options: +:root_wmi+, +:wmi+ (default)
|
197
|
+
# @param [Integer] limit the optional maximum number of results we wish to return
|
198
|
+
# @return [Array] an array of rows returned by the query
|
199
|
+
def values_at(request, conn=:cimv2, limit=nil)
|
200
|
+
super(request, limit)
|
201
|
+
|
202
|
+
rows = case conn
|
203
|
+
when :root_wmi
|
204
|
+
@root_wmi.ExecQuery(request, nil, 48)
|
205
|
+
when :cimv2
|
206
|
+
@wmi.ExecQuery(request, nil, 48)
|
207
|
+
end
|
208
|
+
|
209
|
+
return_data = []
|
210
|
+
|
211
|
+
i = 0
|
212
|
+
|
213
|
+
rows.each do |row|
|
214
|
+
i += 1
|
215
|
+
|
216
|
+
return_hash = {}
|
217
|
+
|
218
|
+
row.Properties_.each do |property|
|
219
|
+
if property.Name =~ /^attributes/i && property.Value.kind_of?(WIN32OLE)
|
220
|
+
row.Attributes.Properties_.each do |property|
|
221
|
+
return_hash[property.Name.downcase.to_sym] = property.Value
|
222
|
+
end
|
223
|
+
else
|
224
|
+
return_hash[property.Name.downcase.to_sym] = property.Value
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
return_data << return_hash
|
229
|
+
|
230
|
+
break if (limit.nil? && i == limit)
|
231
|
+
end
|
232
|
+
|
233
|
+
debug "#{return_data.size} row(s) returned"
|
234
|
+
|
235
|
+
return return_data
|
236
|
+
end
|
237
|
+
|
238
|
+
|
239
|
+
|
185
240
|
end
|
186
241
|
end
|
data/lib/boris/errors.rb
CHANGED
data/lib/boris/helpers/array.rb
CHANGED
@@ -1,63 +1,63 @@
|
|
1
|
-
class Array
|
2
|
-
def strip_string_values_in_array
|
3
|
-
self.map! do |val|
|
4
|
-
val.strip_string_values_in_array if val.is_a?(Array)
|
5
|
-
val.strip_string_values_in_hash if val.is_a?(Hash)
|
6
|
-
val.is_a?(String) ? val.strip : val
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
def to_ms_product_key
|
11
|
-
valid_chars = 'BCDFGHJKMPQRTVWXY2346789'.scan(/./)
|
12
|
-
|
13
|
-
product_key = nil
|
14
|
-
|
15
|
-
raw_product_key = []
|
16
|
-
|
17
|
-
52.upto(66) do |idx|
|
18
|
-
raw_product_key << self[idx]
|
19
|
-
end
|
20
|
-
|
21
|
-
24.downto(0) do |a|
|
22
|
-
b = 0
|
23
|
-
|
24
|
-
14.downto(0) do |c|
|
25
|
-
b = b * 256 ^ raw_product_key[c]
|
26
|
-
raw_product_key[c] = (b / 24).to_i
|
27
|
-
b = b.remainder(24)
|
28
|
-
end
|
29
|
-
|
30
|
-
product_key = "#{valid_chars[b]}#{product_key}"
|
31
|
-
|
32
|
-
if a.remainder(5) == 0 && a != 0
|
33
|
-
product_key = "-#{product_key}"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
return product_key.upcase
|
38
|
-
end
|
39
|
-
|
40
|
-
def to_nil_hash
|
41
|
-
h = Hash.new
|
42
|
-
self.each do |item|
|
43
|
-
if item.kind_of?(Hash)
|
44
|
-
h.merge!(item)
|
45
|
-
else
|
46
|
-
h[item.to_sym] = nil
|
47
|
-
end
|
48
|
-
end
|
49
|
-
return h
|
50
|
-
end
|
51
|
-
|
52
|
-
def to_wwn
|
53
|
-
wwn = []
|
54
|
-
|
55
|
-
0.upto(7) do |i|
|
56
|
-
hex = self[i].to_s(16)
|
57
|
-
hex = "0#{hex}" if self[i] < 16
|
58
|
-
wwn << hex
|
59
|
-
end
|
60
|
-
|
61
|
-
return wwn.join
|
62
|
-
end
|
1
|
+
class Array
|
2
|
+
def strip_string_values_in_array
|
3
|
+
self.map! do |val|
|
4
|
+
val.strip_string_values_in_array if val.is_a?(Array)
|
5
|
+
val.strip_string_values_in_hash if val.is_a?(Hash)
|
6
|
+
val.is_a?(String) ? val.strip : val
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_ms_product_key
|
11
|
+
valid_chars = 'BCDFGHJKMPQRTVWXY2346789'.scan(/./)
|
12
|
+
|
13
|
+
product_key = nil
|
14
|
+
|
15
|
+
raw_product_key = []
|
16
|
+
|
17
|
+
52.upto(66) do |idx|
|
18
|
+
raw_product_key << self[idx]
|
19
|
+
end
|
20
|
+
|
21
|
+
24.downto(0) do |a|
|
22
|
+
b = 0
|
23
|
+
|
24
|
+
14.downto(0) do |c|
|
25
|
+
b = b * 256 ^ raw_product_key[c]
|
26
|
+
raw_product_key[c] = (b / 24).to_i
|
27
|
+
b = b.remainder(24)
|
28
|
+
end
|
29
|
+
|
30
|
+
product_key = "#{valid_chars[b]}#{product_key}"
|
31
|
+
|
32
|
+
if a.remainder(5) == 0 && a != 0
|
33
|
+
product_key = "-#{product_key}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
return product_key.upcase
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_nil_hash
|
41
|
+
h = Hash.new
|
42
|
+
self.each do |item|
|
43
|
+
if item.kind_of?(Hash)
|
44
|
+
h.merge!(item)
|
45
|
+
else
|
46
|
+
h[item.to_sym] = nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
return h
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_wwn
|
53
|
+
wwn = []
|
54
|
+
|
55
|
+
0.upto(7) do |i|
|
56
|
+
hex = self[i].to_s(16)
|
57
|
+
hex = "0#{hex}" if self[i] < 16
|
58
|
+
wwn << hex
|
59
|
+
end
|
60
|
+
|
61
|
+
return wwn.join
|
62
|
+
end
|
63
63
|
end
|
@@ -1,20 +1,23 @@
|
|
1
|
-
module Boris
|
2
|
-
VENDOR_ADOBE = 'Adobe Systems, Inc.'
|
3
|
-
VENDOR_AMD = 'AMD, Inc.'
|
4
|
-
VENDOR_APC = 'APC Corp.'
|
5
|
-
VENDOR_BROCADE = 'Brocade Communications Corp.'
|
6
|
-
VENDOR_CISCO = 'Cisco Systems, Inc.'
|
7
|
-
VENDOR_CITRIX = 'Citrix Systems, Inc.'
|
8
|
-
VENDOR_DELL = 'Dell Inc.'
|
9
|
-
VENDOR_EMULEX = 'Emulex Corp.'
|
10
|
-
VENDOR_F5 = 'F5 Networks, Inc.'
|
11
|
-
VENDOR_HP = 'Hewlett Packard, Inc.'
|
12
|
-
VENDOR_IBM = 'IBM Corp.'
|
13
|
-
VENDOR_INTEL = 'Intel Corp.'
|
14
|
-
VENDOR_MICROSOFT = 'Microsoft Corp.'
|
15
|
-
VENDOR_ORACLE = 'Oracle Corp.'
|
16
|
-
VENDOR_QLOGIC = 'QLogic Corp.'
|
17
|
-
VENDOR_REDHAT = 'Red Hat Inc.'
|
18
|
-
VENDOR_SUSE = 'SUSE Linux GmbH'
|
19
|
-
VENDOR_VMWARE = 'VMware, Inc.'
|
1
|
+
module Boris
|
2
|
+
VENDOR_ADOBE = 'Adobe Systems, Inc.'
|
3
|
+
VENDOR_AMD = 'AMD, Inc.'
|
4
|
+
VENDOR_APC = 'APC Corp.'
|
5
|
+
VENDOR_BROCADE = 'Brocade Communications Corp.'
|
6
|
+
VENDOR_CISCO = 'Cisco Systems, Inc.'
|
7
|
+
VENDOR_CITRIX = 'Citrix Systems, Inc.'
|
8
|
+
VENDOR_DELL = 'Dell Inc.'
|
9
|
+
VENDOR_EMULEX = 'Emulex Corp.'
|
10
|
+
VENDOR_F5 = 'F5 Networks, Inc.'
|
11
|
+
VENDOR_HP = 'Hewlett Packard, Inc.'
|
12
|
+
VENDOR_IBM = 'IBM Corp.'
|
13
|
+
VENDOR_INTEL = 'Intel Corp.'
|
14
|
+
VENDOR_MICROSOFT = 'Microsoft Corp.'
|
15
|
+
VENDOR_ORACLE = 'Oracle Corp.'
|
16
|
+
VENDOR_QLOGIC = 'QLogic Corp.'
|
17
|
+
VENDOR_REDHAT = 'Red Hat Inc.'
|
18
|
+
VENDOR_SUSE = 'SUSE Linux GmbH'
|
19
|
+
VENDOR_VMWARE = 'VMware, Inc.'
|
20
|
+
|
21
|
+
PORT_DEFAULTS = {:ssh=>22, :wmi=>135}
|
22
|
+
VALID_CONNECTION_TYPES = [:snmp, :ssh, :wmi]
|
20
23
|
end
|
data/lib/boris/helpers/hash.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
class Hash
|
2
|
-
def strip_string_values_in_hash
|
3
|
-
self.each_pair do |key, val|
|
4
|
-
val.strip_string_values_in_array if val.is_a?(Array)
|
5
|
-
self[key] = val.strip if val.is_a?(String)
|
6
|
-
end
|
7
|
-
end
|
1
|
+
class Hash
|
2
|
+
def strip_string_values_in_hash
|
3
|
+
self.each_pair do |key, val|
|
4
|
+
val.strip_string_values_in_array if val.is_a?(Array)
|
5
|
+
self[key] = val.strip if val.is_a?(String)
|
6
|
+
end
|
7
|
+
end
|
8
8
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'boris/lumberjack'
|
2
|
+
|
3
|
+
module Boris
|
4
|
+
module Network
|
5
|
+
extend Lumberjack
|
6
|
+
|
7
|
+
# Attempts to suggest a connection method based on whether certain TCP ports
|
8
|
+
# on the target are responding (22 for SSH, 135 for WMI by default). Can be
|
9
|
+
# used to speed up the process of determining whether we should try to
|
10
|
+
# connect to our host using different methods, or bypass certain attempts
|
11
|
+
# entirely.
|
12
|
+
#
|
13
|
+
# Boris::Network.suggested_connection_method('linuxserver01') #=> :ssh
|
14
|
+
#
|
15
|
+
# @param target name we wish to test against
|
16
|
+
# @return [Symbol] returns :wmi, :ssh, or nil
|
17
|
+
# @see tcp_port_responding?
|
18
|
+
def self.suggested_connection_method(target)
|
19
|
+
connection_method = nil
|
20
|
+
|
21
|
+
PORT_DEFAULTS.each_pair do |key, val|
|
22
|
+
break if connection_method
|
23
|
+
|
24
|
+
debug "detecting if #{key.to_s} is available"
|
25
|
+
|
26
|
+
if tcp_port_responding?(target, val)
|
27
|
+
debug "#{key.to_s} seems to be available"
|
28
|
+
connection_method = key
|
29
|
+
else
|
30
|
+
info 'wmi does not appear to be responding'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
info 'failed to detect connection method' if connection_method.nil?
|
35
|
+
connection_method
|
36
|
+
end
|
37
|
+
|
38
|
+
# Checks if the supplied TCP port is responding on the target. Useful for
|
39
|
+
# determining which connection type we should use instead of taking more
|
40
|
+
# time connecting to the target using different methods just to check if
|
41
|
+
# they succeed or not.
|
42
|
+
#
|
43
|
+
# Boris::Network.tcp_port_responding?('windowsserver01', 22) #=> false
|
44
|
+
# Boris::Network.tcp_port_responding?('windowsserver01', 135) #=> true
|
45
|
+
#
|
46
|
+
# @param target name we wish to test against
|
47
|
+
# @param port the TCP port number we wish to test
|
48
|
+
# @return [Boolean] returns true of the supplied port is responding
|
49
|
+
def self.tcp_port_responding?(target, port)
|
50
|
+
status = false
|
51
|
+
|
52
|
+
debug "checking if port #{port} is responding"
|
53
|
+
|
54
|
+
begin
|
55
|
+
conn = TCPSocket.new(target, port)
|
56
|
+
info "port #{port} is responding"
|
57
|
+
conn.close
|
58
|
+
debug "connection to port closed"
|
59
|
+
status = true
|
60
|
+
rescue
|
61
|
+
info "port #{port} is not responding"
|
62
|
+
status = false
|
63
|
+
end
|
64
|
+
|
65
|
+
status
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|