boris 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/LICENSE.md +9 -0
  2. data/README.md +94 -0
  3. data/boris.gemspec +28 -0
  4. data/doc/Array.html +437 -0
  5. data/doc/Boris.html +230 -0
  6. data/doc/Boris/ConnectionAlreadyActive.html +123 -0
  7. data/doc/Boris/ConnectionFailed.html +127 -0
  8. data/doc/Boris/Connector.html +794 -0
  9. data/doc/Boris/InvalidCredentials.html +131 -0
  10. data/doc/Boris/InvalidOption.html +123 -0
  11. data/doc/Boris/InvalidTargetName.html +123 -0
  12. data/doc/Boris/Lumberjack.html +466 -0
  13. data/doc/Boris/MissingCredentials.html +123 -0
  14. data/doc/Boris/NoActiveConnection.html +123 -0
  15. data/doc/Boris/NoProfileDetected.html +123 -0
  16. data/doc/Boris/Options.html +783 -0
  17. data/doc/Boris/Profiles.html +117 -0
  18. data/doc/Boris/Profiles/Linux.html +1151 -0
  19. data/doc/Boris/Profiles/RedHat.html +875 -0
  20. data/doc/Boris/Profiles/Solaris.html +1230 -0
  21. data/doc/Boris/Profiles/Structure.html +2050 -0
  22. data/doc/Boris/Profiles/UNIX.html +893 -0
  23. data/doc/Boris/Profiles/Windows.html +1846 -0
  24. data/doc/Boris/Profiles/Windows/Windows2003.html +304 -0
  25. data/doc/Boris/Profiles/Windows/Windows2008.html +379 -0
  26. data/doc/Boris/Profiles/Windows/Windows2012.html +304 -0
  27. data/doc/Boris/SNMPConnector.html +512 -0
  28. data/doc/Boris/SSHConnector.html +633 -0
  29. data/doc/Boris/Target.html +2002 -0
  30. data/doc/Boris/WMIConnector.html +1134 -0
  31. data/doc/BorisLogger.html +217 -0
  32. data/doc/Hash.html +195 -0
  33. data/doc/String.html +1246 -0
  34. data/doc/_index.html +420 -0
  35. data/doc/class_list.html +53 -0
  36. data/doc/css/common.css +1 -0
  37. data/doc/css/full_list.css +57 -0
  38. data/doc/css/style.css +328 -0
  39. data/doc/file.README.html +183 -0
  40. data/doc/file_list.html +55 -0
  41. data/doc/frames.html +28 -0
  42. data/doc/index.html +183 -0
  43. data/doc/js/app.js +214 -0
  44. data/doc/js/full_list.js +173 -0
  45. data/doc/js/jquery.js +4 -0
  46. data/doc/method_list.html +1468 -0
  47. data/doc/top-level-namespace.html +126 -0
  48. data/lib/boris.rb +30 -0
  49. data/lib/boris/connectors.rb +47 -0
  50. data/lib/boris/connectors/snmp.rb +56 -0
  51. data/lib/boris/connectors/ssh.rb +110 -0
  52. data/lib/boris/connectors/wmi.rb +186 -0
  53. data/lib/boris/errors.rb +17 -0
  54. data/lib/boris/helpers/array.rb +63 -0
  55. data/lib/boris/helpers/constants.rb +20 -0
  56. data/lib/boris/helpers/hash.rb +8 -0
  57. data/lib/boris/helpers/scrubber.rb +51 -0
  58. data/lib/boris/helpers/string.rb +130 -0
  59. data/lib/boris/lumberjack.rb +47 -0
  60. data/lib/boris/options.rb +86 -0
  61. data/lib/boris/profiles/linux/redhat.rb +77 -0
  62. data/lib/boris/profiles/linux_core.rb +216 -0
  63. data/lib/boris/profiles/unix/solaris.rb +307 -0
  64. data/lib/boris/profiles/unix_core.rb +85 -0
  65. data/lib/boris/profiles/windows/windows2003.rb +15 -0
  66. data/lib/boris/profiles/windows/windows2008.rb +23 -0
  67. data/lib/boris/profiles/windows/windows2012.rb +15 -0
  68. data/lib/boris/profiles/windows_core.rb +530 -0
  69. data/lib/boris/structure.rb +167 -0
  70. data/lib/boris/target.rb +340 -0
  71. data/test/connector_tests/test_snmp.rb +35 -0
  72. data/test/connector_tests/test_ssh.rb +51 -0
  73. data/test/connector_tests/test_wmi.rb +129 -0
  74. data/test/helper_tests/test_array.rb +25 -0
  75. data/test/helper_tests/test_hash.rb +10 -0
  76. data/test/helper_tests/test_string.rb +136 -0
  77. data/test/profile_tests/test_core_skeleton +107 -0
  78. data/test/profile_tests/test_linux_core.rb +331 -0
  79. data/test/profile_tests/test_redhat.rb +134 -0
  80. data/test/profile_tests/test_solaris.rb +523 -0
  81. data/test/profile_tests/test_unix_core.rb +117 -0
  82. data/test/profile_tests/test_windows.rb +536 -0
  83. data/test/setup_tests.rb +14 -0
  84. data/test/test_all.rb +8 -0
  85. data/test/test_options.rb +44 -0
  86. data/test/test_structure.rb +136 -0
  87. data/test/test_target.rb +146 -0
  88. metadata +241 -0
@@ -0,0 +1,126 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.8.3
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ hasFrames = window.top.frames.main ? true : false;
19
+ relpath = '';
20
+ framesUrl = "frames.html#!" + escape(window.location.href);
21
+ </script>
22
+
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
25
+
26
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
27
+
28
+
29
+ </head>
30
+ <body>
31
+ <div id="header">
32
+ <div id="menu">
33
+
34
+ <a href="_index.html">Index</a> &raquo;
35
+
36
+
37
+ <span class="title">Top Level Namespace</span>
38
+
39
+
40
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
41
+ </div>
42
+
43
+ <div id="search">
44
+
45
+ <a class="full_list_link" id="class_list_link"
46
+ href="class_list.html">
47
+ Class List
48
+ </a>
49
+
50
+ <a class="full_list_link" id="method_list_link"
51
+ href="method_list.html">
52
+ Method List
53
+ </a>
54
+
55
+ <a class="full_list_link" id="file_list_link"
56
+ href="file_list.html">
57
+ File List
58
+ </a>
59
+
60
+ </div>
61
+ <div class="clear"></div>
62
+ </div>
63
+
64
+ <iframe id="search_frame"></iframe>
65
+
66
+ <div id="content"><h1>Top Level Namespace
67
+
68
+
69
+
70
+ </h1>
71
+
72
+ <dl class="box">
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+ </dl>
82
+ <div class="clear"></div>
83
+
84
+ <h2>Defined Under Namespace</h2>
85
+ <p class="children">
86
+
87
+
88
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="Boris.html" title="Boris (module)">Boris</a></span>
89
+
90
+
91
+
92
+ <strong class="classes">Classes:</strong> <span class='object_link'><a href="Array.html" title="Array (class)">Array</a></span>, <span class='object_link'><a href="BorisLogger.html" title="BorisLogger (class)">BorisLogger</a></span>, <span class='object_link'><a href="Hash.html" title="Hash (class)">Hash</a></span>, <span class='object_link'><a href="String.html" title="String (class)">String</a></span>
93
+
94
+
95
+ </p>
96
+
97
+ <h2>Constant Summary</h2>
98
+
99
+ <dl class="constants">
100
+
101
+ <dt id="PLATFORM-constant" class="">PLATFORM =
102
+
103
+ </dt>
104
+ <dd><pre class="code"><span class='const'>RbConfig</span><span class='op'>::</span><span class='const'>CONFIG</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>host_os</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span> <span class='op'>=~</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>mswin|mingw|cygwin</span><span class='regexp_end'>/</span></span> <span class='op'>?</span> <span class='symbol'>:win32</span> <span class='op'>:</span> <span class='const'>RbConfig</span><span class='op'>::</span><span class='const'>CONFIG</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>host_os</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span></pre></dd>
105
+
106
+ </dl>
107
+
108
+
109
+
110
+
111
+
112
+
113
+
114
+
115
+
116
+
117
+ </div>
118
+
119
+ <div id="footer">
120
+ Generated on Sun Feb 3 16:32:41 2013 by
121
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
122
+ 0.8.3 (ruby-1.9.3).
123
+ </div>
124
+
125
+ </body>
126
+ </html>
data/lib/boris.rb ADDED
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+
3
+ PLATFORM = RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ ? :win32 : RbConfig::CONFIG['host_os']
4
+
5
+ require 'date'
6
+ require 'json'
7
+ require 'logger'
8
+ require 'netaddr'
9
+ require 'net/ssh'
10
+ require 'rbconfig'
11
+ require 'snmp'
12
+ require 'socket'
13
+ require 'thread'
14
+ require 'win32ole' if PLATFORM == :win32
15
+
16
+ require 'boris/lumberjack'
17
+
18
+ require 'boris/errors'
19
+ require 'boris/options'
20
+ require 'boris/target'
21
+
22
+ require 'boris/helpers/array'
23
+ require 'boris/helpers/constants'
24
+ require 'boris/helpers/hash'
25
+ require 'boris/helpers/scrubber'
26
+ require 'boris/helpers/string'
27
+
28
+ module Boris
29
+
30
+ end
@@ -0,0 +1,47 @@
1
+ module Boris
2
+ class Connector
3
+ include Lumberjack
4
+
5
+ attr_reader :connected
6
+ attr_reader :host
7
+ attr_reader :options
8
+ attr_reader :reconnectable
9
+
10
+ def initialize(host, cred, options, logger=nil)
11
+ debug 'creating connection object'
12
+
13
+ @host = host
14
+ @user = cred[:user]
15
+ @password = cred[:password]
16
+ @connected = false
17
+ @reconnectable = true
18
+
19
+ @logger = logger
20
+ end
21
+
22
+ def connected?
23
+ @connected
24
+ end
25
+
26
+ def disconnect
27
+ debug 'closing connection to host'
28
+ @connected = false
29
+ end
30
+
31
+ def establish_connection
32
+ debug 'attempting connection'
33
+ end
34
+
35
+ def values_at(request, limit)
36
+ if !limit.kind_of?(Integer)
37
+ raise ArgumentError, "non-integer limit specified (#{limit.inspect})"
38
+ elsif limit < 1
39
+ raise ArgumentError, "specified limit must be greater than 1 (or nil for no limit) (#{limit.inspect})"
40
+ end unless limit.nil?
41
+
42
+ amount = limit == 1 ? 'single value' : 'multiple values'
43
+
44
+ debug "issuing request for #{amount} (#{request.inspect})"
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,56 @@
1
+ require 'boris/connectors'
2
+
3
+ module Boris
4
+ class SNMPConnector < Connector
5
+ def initialize(host, cred, options, logger=nil)
6
+ super(host, cred, options, logger)
7
+ @snmp_options = options[:snmp_options].merge(:host=>@host, :version=>:SNMPv1, :community=>@user)
8
+
9
+ #snmp connections are always reconnectable
10
+ @reconnectable = true
11
+ end
12
+
13
+ def disconnect
14
+ super
15
+ @transport = nil
16
+ debug 'connections closed'
17
+ end
18
+
19
+ def establish_connection
20
+ super
21
+
22
+ begin
23
+ @transport = SNMP::Manager.new(@snmp_options)
24
+ value_at('sysDescr')
25
+ debug 'connection established'
26
+ @connected = true
27
+ rescue SNMP::RequestTimeout
28
+ warn 'connection failed (connection timeout)'
29
+ rescue => error
30
+ warn "connection failed (#{error.message})"
31
+ end
32
+
33
+ return self
34
+ end
35
+
36
+ def value_at(request)
37
+ values_at(request, 1)[0]
38
+ end
39
+
40
+ def values_at(request, limit=nil)
41
+ super(request, limit)
42
+
43
+ return_data = []
44
+
45
+ @transport.walk(request) do |row|
46
+ row.each {|item| return_data << {:name=>item.name.to_s, :value=>item.value}}
47
+ end
48
+
49
+ info "#{return_data.size} row(s) returned"
50
+
51
+ limit = return_data.size if limit.nil?
52
+
53
+ return_data[0..limit]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,110 @@
1
+ require 'boris/connectors'
2
+
3
+ module Boris
4
+ class SSHConnector < Connector
5
+ def initialize(host, cred, options, logger=nil)
6
+ @ssh_options = options[:ssh_options]
7
+ @ssh_options[:password] = @password if @password
8
+
9
+ invalid_ssh_options = @ssh_options.keys - Net::SSH::VALID_OPTIONS
10
+ raise ArgumentError, "invalid ssh option(s): #{invalid_ssh_options.join(', ')}" if invalid_ssh_options.any?
11
+
12
+ super(host, cred, options, logger)
13
+ end
14
+
15
+ def disconnect
16
+ super
17
+ @transport = nil
18
+ debug 'connections closed'
19
+ end
20
+
21
+ def establish_connection
22
+ super
23
+
24
+ begin
25
+ @transport = Net::SSH.start(@host, @user, @ssh_options)
26
+ debug 'connection established'
27
+ @connected = @reconnectable = true
28
+ rescue Net::SSH::AuthenticationFailed
29
+ warn "connection failed (connection made but credentials not accepted with user #{@user})"
30
+ @reconnectable = true
31
+ rescue Net::SSH::HostKeyMismatch
32
+ warn 'connection failed (host key mismatch)'
33
+ @reconnectable = false
34
+ rescue => error
35
+ warn "connection failed (#{error.message})"
36
+ @reconnectable = true
37
+ end
38
+
39
+ if @reconnectable == true
40
+ info 'connection available for retry'
41
+ elsif @reconnectable == false
42
+ info 'connection does not seem to be available (so we will not retry)'
43
+ end unless @transport
44
+
45
+ return self
46
+ end
47
+
48
+ def value_at(request, request_pty=false)
49
+ values_at(request, request_pty, 1)[0]
50
+ end
51
+
52
+ def values_at(request, request_pty=false, limit=nil)
53
+ super(request, limit)
54
+
55
+ error_messages = []
56
+ reconnect = false
57
+ return_data = []
58
+
59
+ chan = @transport.open_channel do |chan|
60
+ if request_pty
61
+ debug 'requsting pty...'
62
+ chan.request_pty()
63
+ debug 'pty successfully requested'
64
+ end
65
+
66
+ chan.on_data do |ch, data|
67
+ if data =~ /^\[sudo\] password for/i
68
+ debug 'system asking for password for sudo request'
69
+ if @password
70
+ ch.send_data "#{@password}\n"
71
+ debug 'password sent'
72
+ else
73
+ ch.close
74
+ info "channel closed (we don't have a password to supply)"
75
+ end
76
+ elsif data =~ /sorry, try again/i
77
+ ch.close
78
+ return_data = []
79
+ info "channel closed (we have a password to supply but system its not accepted)"
80
+ elsif data =~ /permission denied/i
81
+ warn "permission denied for this request (#{data.gsub(/\n|\s+/, ', ')})"
82
+ else
83
+ return_data << data
84
+ end
85
+ end
86
+
87
+ # called when something is written to stderr
88
+ chan.on_extended_data do |ch, type, data|
89
+ error_messages.concat(data.split(/\n/))
90
+ end
91
+
92
+ chan.exec(request)
93
+ end
94
+
95
+ chan.wait
96
+
97
+ if !error_messages.empty?
98
+ warn "message written to STDERR for this request (#{error_messages.join('. ')})"
99
+ end
100
+
101
+ return_data = return_data.join.split(/\n/)
102
+
103
+ info "#{return_data.size} row(s) returned"
104
+
105
+ limit = return_data.size if limit.nil?
106
+
107
+ return_data[0..limit]
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,186 @@
1
+ require 'boris/connectors'
2
+
3
+ module Boris
4
+ class WMIConnector < Connector
5
+ attr_accessor :wmi, :root_wmi, :registry
6
+
7
+ HKEY_LOCAL_MACHINE = 0x80000002
8
+ KEY_QUERY_VALUE = 1
9
+ KEY_ENUMERATE_SUB_KEYS = 8
10
+
11
+ def initialize(host, cred, options, logger=nil)
12
+ super(host, cred, options, logger)
13
+ end
14
+
15
+ def disconnect
16
+ super
17
+ @wmi = nil
18
+ @registry = nil
19
+ @root_wmi = nil
20
+
21
+ debug 'connections closed'
22
+ end
23
+
24
+ def establish_connection
25
+ super
26
+
27
+ begin
28
+ locator = WIN32OLE.new('WbemScripting.SWbemLocator')
29
+
30
+ debug 'attempting connection to cimv2 namespace'
31
+ @wmi = locator.ConnectServer(@host, 'root\cimv2', @user, @password, nil, nil, 128)
32
+ debug 'connection to cimv2 namespace successful'
33
+
34
+ debug 'attempting connection to wmi root namespace'
35
+ @root_wmi = locator.ConnectServer(@host, 'root\WMI', @user, @password, nil, nil, 128)
36
+ debug 'connection to wmi root namespace successful'
37
+
38
+ debug 'attempting connection to registry'
39
+ @registry = locator.ConnectServer(@host, 'root\default', @user, @password, nil, nil, 128).Get('StdRegProv')
40
+ debug 'connection to registry successful'
41
+
42
+ debug 'all required connections established'
43
+ @connected = @reconnectable = true
44
+
45
+ rescue WIN32OLERuntimeError => error
46
+ @connected = false
47
+ if error.message =~ /access is denied/i
48
+ warn "connection failed (connection made but credentials not accepted with user #{@user})"
49
+ @reconnectable = true
50
+ elsif error.message =~ /rpc server is unavailable/i
51
+ warn 'connection failed (rpc server not available)'
52
+ @reconnectable = false
53
+ else
54
+ warn "connection failed (#{error.message.gsub(/\n\s*/, '. ')})"
55
+ @reconnectable = true
56
+ end
57
+ end
58
+
59
+ if @reconnectable == true
60
+ info 'connection available for retry'
61
+ elsif @reconnectable == false
62
+ info 'connection does not seem to be available (so we will not retry)'
63
+ end unless @transport
64
+
65
+ return self
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
109
+ end
110
+
111
+ def has_access_for(key_path, permission_to_check=nil)
112
+ debug "checking for registry read access for #{key_path}"
113
+
114
+ access_params = @registry.Methods_('CheckAccess').inParameters.SpawnInstance_
115
+
116
+ access_params.hDefKey = HKEY_LOCAL_MACHINE
117
+ access_params.sSubKeyName = key_path
118
+ access_params.uRequired = permission_to_check
119
+
120
+ @registry.ExecMethod_('CheckAccess', access_params).bGranted
121
+ end
122
+
123
+ def registry_subkeys_at(key_path)
124
+ return_data = []
125
+
126
+ debug "reading registry subkeys at path #{key_path}"
127
+
128
+ if has_access_for(key_path, KEY_ENUMERATE_SUB_KEYS)
129
+ in_params = @registry.Methods_('EnumKey').inParameters.SpawnInstance_
130
+ in_params.hDefKey = HKEY_LOCAL_MACHINE
131
+ in_params.sSubKeyName = key_path
132
+
133
+ @registry.ExecMethod_('EnumKey', in_params).sNames.each do |key|
134
+ return_data << key_path + '\\' + key
135
+ end
136
+ else
137
+ info "no access for enumerating keys at (#{key_path})"
138
+ end
139
+
140
+ return return_data
141
+ end
142
+
143
+ def registry_values_at(key_path)
144
+ values = Hash.new
145
+
146
+ debug "reading registry values at path #{key_path}"
147
+
148
+ if has_access_for(key_path, KEY_QUERY_VALUE)
149
+ in_params = @registry.Methods_('EnumValues').inParameters.SpawnInstance_
150
+ in_params.hDefKey = HKEY_LOCAL_MACHINE
151
+ in_params.sSubKeyName = key_path
152
+
153
+ str_params = @registry.Methods_('GetStringValue').inParameters.SpawnInstance_
154
+ str_params.sSubKeyName = key_path
155
+
156
+ subkey_values = @registry.ExecMethod_('EnumValues', in_params).sNames
157
+ subkey_values ||= []
158
+
159
+ subkey_values.each do |value|
160
+ if !value.empty?
161
+ str_params.sValueName = value
162
+
163
+ begin
164
+ x = @registry.ExecMethod_('GetStringValue', str_params).sValue
165
+ x = @registry.ExecMethod_('GetBinaryValue', str_params).uValue unless x
166
+ x = @registry.ExecMethod_('GetDWORDValue', str_params).uValue unless x
167
+ x = @registry.ExecMethod_('GetExpandedStringValue', str_params).sValue unless x
168
+ x = @registry.ExecMethod_('GetMultiStringValue', str_params).sValue unless x
169
+ x = @registry.ExecMethod_('GetQWORDValue', str_params).uValue unless x
170
+
171
+ values[value.downcase.to_sym] = x
172
+ rescue
173
+ if $!.message =~ /#{invalid method}/i
174
+ warn "unreadable registry value (#{key_path}\\#{value})"
175
+ end
176
+ end
177
+ end
178
+ end
179
+ else
180
+ info "no access for enumerating values at (#{key_path})"
181
+ end
182
+
183
+ return values
184
+ end
185
+ end
186
+ end