winrm 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,53 @@
1
+ --------------------------------------------------------------------------
2
+ Windows Remote Management (WinRM) for Ruby
3
+ --------------------------------------------------------------------------
4
+ This is a SOAP library that uses the functionality in Windows Remote
5
+ Management(WinRM) to call native object in Windows. This includes, but is
6
+ not limitted to, running batch scripts, powershell scripts and fetching WMI
7
+ variables. For more information on WinRM, please visit Microsoft's WinRM
8
+ site: http://msdn.microsoft.com/en-us/library/aa384426(v=VS.85).aspx
9
+
10
+
11
+ My Info:
12
+ BLOG: http://distributed-frostbite.blogspot.com/
13
+ Add me in LinkedIn: http://www.linkedin.com/in/danwanek
14
+
15
+ --------------------------------------------------------------------------
16
+ --------------------------------------------------------------------------
17
+ TO USE:
18
+ require 'winrm'
19
+ # See REQUIRED GEMS below
20
+
21
+ gem install -r winrm
22
+
23
+ REQUIRED GEMS: (These should automatically install with the winrm gem)
24
+ # Handsoap
25
+ gem install -r handsoap
26
+ # Nokogiri XML Parser
27
+ gem install -r nokogiri
28
+ # HttpClient
29
+ gem install -r httpclient
30
+ # NTLM Library
31
+ gem install -r rubyntlm
32
+ #UUID Library
33
+ gem install -r uuid
34
+
35
+
36
+ EXAMPLE:
37
+ require 'winrm'
38
+ WinRM::WinRM.endpoint = 'http://mywinrmhost:5985/wsman'
39
+ WinRM::WinRM.set_auth('user','password')
40
+ winrm = WinRM::WinRM.instance
41
+ output = winrm.winrm.run_powershell_script 'script.ps1'
42
+ puts output[:stdout]
43
+
44
+ --------------------------------------------------------------------------
45
+ DISCLAIMER: If you see something that could be done better or would like
46
+ to help out in the development of this code please feel free to clone the
47
+ 'git' repository and send me patches:
48
+ git clone git://github.com/zenchild/WinRM.git
49
+ or add an issue on GitHub:
50
+ http://github.com/zenchild/WinRM/issues
51
+
52
+ Cheers!
53
+ --------------------------------------------------------------------------
data/Rakefile ADDED
@@ -0,0 +1,69 @@
1
+ require 'rubygems'
2
+ require 'rake/clean'
3
+ require 'rake/gempackagetask'
4
+ require 'date'
5
+
6
+ CLEAN.include("pkg")
7
+ CLEAN.include("doc")
8
+
9
+ GEMSPEC = Gem::Specification.new do |gem|
10
+ gem.name = "winrm"
11
+ gem.version = File.open('VERSION').readline.chomp
12
+ gem.date = Date.today.to_s
13
+ gem.platform = Gem::Platform::RUBY
14
+ gem.rubyforge_project = nil
15
+
16
+ gem.author = "Dan Wanek"
17
+ gem.email = "dan.wanek@gmail.com"
18
+ gem.homepage = "http://github.com/zenchild/WinRM"
19
+
20
+ gem.summary = 'Ruby library for Windows Remote Management'
21
+ gem.description = <<-EOF
22
+ Ruby library for Windows Remote Management
23
+ EOF
24
+
25
+ gem.files = `git ls-files`.split(/\n/)
26
+ gem.require_path = "lib"
27
+ gem.rdoc_options = %w(-x test/ -x examples/)
28
+ gem.extra_rdoc_files = %w(README COPYING.txt)
29
+
30
+ gem.required_ruby_version = '>= 1.8.7'
31
+ gem.add_runtime_dependency 'handsoap'
32
+ gem.add_runtime_dependency 'nokogiri'
33
+ gem.add_runtime_dependency 'httpclient'
34
+ gem.add_runtime_dependency 'rubyntlm'
35
+ gem.add_runtime_dependency 'uuid'
36
+ end
37
+
38
+ Rake::GemPackageTask.new(GEMSPEC) do |pkg|
39
+ pkg.need_tar = true
40
+ end
41
+
42
+ task :default => [:buildgem]
43
+
44
+ desc "Build the gem without a version change"
45
+ task :buildgem => [:clean, :repackage]
46
+
47
+ desc "Build the gem, but increment the version first"
48
+ task :newrelease => [:versionup, :clean, :repackage]
49
+
50
+
51
+ desc "Increment the version by 1 minor release"
52
+ task :versionup do
53
+ ver = up_min_version
54
+ puts "New version: #{ver}"
55
+ end
56
+
57
+
58
+ def up_min_version
59
+ f = File.open('VERSION', 'r+')
60
+ ver = f.readline.chomp
61
+ v_arr = ver.split(/\./).map do |v|
62
+ v.to_i
63
+ end
64
+ v_arr[2] += 1
65
+ ver = v_arr.join('.')
66
+ f.rewind
67
+ f.write(ver)
68
+ ver
69
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,37 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of WinRM.
6
+ #
7
+ # WinRM is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # WinRM is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with WinRM. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ # Custom extensions to the class String
22
+ class String
23
+ # Change CamelCased strings to ruby_cased strings
24
+ # It uses the lookahead assertion ?= In this case it basically says match
25
+ # anything followed by a capital letter, but not the capital letter itself.
26
+ # @see http://www.pcre.org/pcre.txt The PCRE guide for more details
27
+ def ruby_case
28
+ self.split(/(?=[A-Z])/).join('_').downcase
29
+ end
30
+
31
+ # Change a ruby_cased string to CamelCased
32
+ def camel_case
33
+ self.split(/_/).map { |i|
34
+ i.sub(/^./) { |s| s.upcase }
35
+ }.join
36
+ end
37
+ end # String
@@ -0,0 +1,28 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of WinRM.
6
+ #
7
+ # WinRM is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # WinRM is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with WinRM. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ module WinRM
22
+ module SOAP
23
+ # Generic WinRM SOAP Error
24
+ class WinRMWebServiceError < StandardError
25
+ end
26
+ end # SOAP
27
+ end # WinRM
28
+
@@ -0,0 +1,36 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of WinRM.
6
+ #
7
+ # WinRM is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # WinRM is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with WinRM. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+ require 'handsoap'
21
+
22
+ module WinRM
23
+ module SOAP
24
+ NS_ADDRESSING ='a' # http://schemas.xmlsoap.org/ws/2004/08/addressing
25
+ NS_CIMBINDING ='b' # http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd
26
+ NS_ENUM ='n' # http://schemas.xmlsoap.org/ws/2004/09/enumeration
27
+ NS_TRANSFER ='x' # http://schemas.xmlsoap.org/ws/2004/09/transfer
28
+ NS_WSMAN_DMTF ='w' # http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
29
+ NS_WSMAN_MSFT ='p' # http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd
30
+ NS_SCHEMA_INST ='xsi' # http://www.w3.org/2001/XMLSchema-instance
31
+ NS_WIN_SHELL ='rsp' # http://schemas.microsoft.com/wbem/wsman/1/windows/shell
32
+ end
33
+ end
34
+
35
+ require 'soap/exceptions/exceptions'
36
+ require 'soap/winrm_service'
@@ -0,0 +1,345 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of WinRM.
6
+ #
7
+ # WinRM is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # WinRM is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with WinRM. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+ Handsoap.http_driver = :http_client
21
+
22
+ module WinRM
23
+ module SOAP
24
+ class WinRMWebService < Handsoap::Service
25
+ include SOAP
26
+
27
+ @@raw_soap = false
28
+
29
+ def initialize()
30
+ if $DEBUG
31
+ @debug = File.new('winrm_debug.out', 'w')
32
+ @debug.sync = true
33
+ end
34
+
35
+ end
36
+
37
+ def self.set_auth(user,pass)
38
+ @@user = user
39
+ @@pass = pass
40
+ end
41
+
42
+ # Turn off parsing and just return the soap response
43
+ def self.raw_soap!
44
+ @@raw_soap = true
45
+ end
46
+
47
+
48
+ # ********* Begin Hooks *********
49
+
50
+ def on_create_document(doc)
51
+ doc.alias NS_ADDRESSING, 'http://schemas.xmlsoap.org/ws/2004/08/addressing'
52
+ doc.alias NS_ENUM, 'http://schemas.xmlsoap.org/ws/2004/09/enumeration'
53
+ doc.alias NS_WSMAN_DMTF, 'http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd'
54
+ doc.alias NS_WSMAN_MSFT, 'http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd'
55
+ doc.alias NS_SCHEMA_INST,'http://www.w3.org/2001/XMLSchema-instance'
56
+ doc.alias NS_WIN_SHELL, 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell'
57
+ doc.alias NS_CIMBINDING, 'http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd'
58
+
59
+ header = doc.find('Header')
60
+ header.add("#{NS_ADDRESSING}:To", WinRMWebService.uri)
61
+ header.add("#{NS_ADDRESSING}:ReplyTo") {|rto|
62
+ rto.add("#{NS_ADDRESSING}:Address",'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous') {|addr|
63
+ addr.set_attr('mustUnderstand','true')
64
+ }
65
+ }
66
+ header.add("#{NS_WSMAN_DMTF}:MaxEnvelopeSize",'153600') {|mes|
67
+ mes.set_attr('mustUnderstand','true')
68
+ }
69
+ header.add("#{NS_ADDRESSING}:MessageID", "uuid:#{UUID.generate.upcase}")
70
+ header.add("#{NS_WSMAN_DMTF}:Locale") {|loc|
71
+ loc.set_attr('xml:lang','en-US')
72
+ loc.set_attr('mustUnderstand','false')
73
+ }
74
+ header.add("#{NS_WSMAN_MSFT}:DataLocale") {|loc|
75
+ loc.set_attr('xml:lang','en-US')
76
+ loc.set_attr('mustUnderstand','false')
77
+ }
78
+ header.add("#{NS_WSMAN_DMTF}:OperationTimeout",'PT60.000S')
79
+ end
80
+
81
+ # Adds knowledge of namespaces to the response object. These have to be identical to the
82
+ # URIs returned in the XML response. For example, I had some issues with the 'soap'
83
+ # namespace because my original URI did not end in a '/'
84
+ # @example
85
+ # Won't work: http://schemas.xmlsoap.org/soap/envelope
86
+ # Works: http://schemas.xmlsoap.org/soap/envelope/
87
+ def on_response_document(doc)
88
+ doc.add_namespace NS_ADDRESSING, 'http://schemas.xmlsoap.org/ws/2004/08/addressing'
89
+ doc.add_namespace NS_ENUM, 'http://schemas.xmlsoap.org/ws/2004/09/enumeration'
90
+ doc.add_namespace NS_TRANSFER, 'http://schemas.xmlsoap.org/ws/2004/09/transfer'
91
+ doc.add_namespace NS_WSMAN_DMTF, 'http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd'
92
+ doc.add_namespace NS_WSMAN_MSFT, 'http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd'
93
+ doc.add_namespace NS_WIN_SHELL, 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell'
94
+ doc.add_namespace NS_CIMBINDING, 'http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd'
95
+ end
96
+
97
+ def on_after_create_http_request(req)
98
+ req.set_auth @@user, @@pass
99
+ req.set_header('Content-Type','application/soap+xml;charset=UTF-8')
100
+ #puts "SOAP DOCUMENT=\n#{req.body}"
101
+ end
102
+
103
+ def on_http_error(resp)
104
+ puts "HTTP ERROR: #{resp.status}"
105
+ puts "HEADERS=\n#{resp.headers}"
106
+ puts "BODY=\n#{resp.body}"
107
+ end
108
+
109
+
110
+ # ********** End Hooks **********
111
+
112
+
113
+ # Create a Shell on the destination host
114
+ # @param [String<optional>] i_stream Which input stream to open. Leave this alone unless you know what you're doing
115
+ # @param [String<optional>] o_stream Which output stream to open. Leave this alone unless you know what you're doing
116
+ # @return [String] The ShellId from the SOAP response. This is our open shell instance on the remote machine.
117
+ def open_shell(i_stream = 'stdin', o_stream = 'stdout stderr')
118
+ header = {
119
+ "#{NS_WSMAN_DMTF}:OptionSet" => [
120
+ {"#{NS_WSMAN_DMTF}:Option" => {:name => 'WINRS_NOPROFILE', :text =>"FALSE"}},
121
+ {"#{NS_WSMAN_DMTF}:Option" => {:name => 'WINRS_CODEPAGE', :text =>"437"}}
122
+ ]
123
+ }.merge(resource_uri_cmd).merge(action_create)
124
+
125
+ resp = invoke("#{NS_WIN_SHELL}:Shell", {:soap_action => :auto, :http_options => nil, :soap_header => header}) do |shell|
126
+ shell.add("#{NS_WIN_SHELL}:InputStreams", i_stream)
127
+ shell.add("#{NS_WIN_SHELL}:OutputStreams",o_stream)
128
+ end
129
+
130
+ # Get the Shell ID from the response
131
+ (resp/"//*[@Name='ShellId']").to_s
132
+ end
133
+
134
+ # Run a command on a machine with an open shell
135
+ # @param [String] shell_id The shell id on the remote machine. See #open_shell
136
+ # @param [String] command The command to run on the remote machine
137
+ # @return [String] The CommandId from the SOAP response. This is the ID we need to query in order to get output.
138
+ def run_command(shell_id, command)
139
+ header = {
140
+ "#{NS_WSMAN_DMTF}:OptionSet" => {
141
+ "#{NS_WSMAN_DMTF}:Option" => {:name => 'WINRS_CONSOLEMODE_STDIN', :text =>"TRUE"},
142
+ }
143
+ }.merge(resource_uri_cmd).merge(action_command).merge(selector_shell_id(shell_id))
144
+
145
+ # Issue the Command
146
+ resp = invoke("#{NS_WIN_SHELL}:CommandLine", {:soap_action => :auto, :http_options => nil, :soap_header => header}) do |cli|
147
+ cli.add("#{NS_WIN_SHELL}:Command","\"#{command}\"")
148
+ end
149
+
150
+ (resp/"//#{NS_WIN_SHELL}:CommandId").to_s
151
+ end
152
+
153
+ # Get the Output of the given shell and command
154
+ # @param [String] shell_id The shell id on the remote machine. See #open_shell
155
+ # @param [String] command_id The command id on the remote machine. See #run_command
156
+ # @return [Hash] :stdout and :stderr
157
+ def get_command_output(shell_id, command_id)
158
+ header = {}.merge(resource_uri_cmd).merge(action_receive).merge(selector_shell_id(shell_id))
159
+
160
+ # Get Command Output
161
+ resp = invoke("#{NS_WIN_SHELL}:Receive", {:soap_action => :auto, :http_options => nil, :soap_header => header}) do |rec|
162
+ rec.add("#{NS_WIN_SHELL}:DesiredStream",'stdout stderr') do |ds|
163
+ ds.set_attr('CommandId', command_id)
164
+ end
165
+ end
166
+
167
+ cmd_stdout = ''
168
+ cmd_stderr = ''
169
+ (resp/"//*[@Name='stdout']").each do |n|
170
+ next if n.to_s.nil?
171
+ cmd_stdout << Base64.decode64(n.to_s)
172
+ end
173
+ (resp/"//*[@Name='stderr']").each do |n|
174
+ next if n.to_s.nil?
175
+ cmd_stderr << Base64.decode64(n.to_s)
176
+ end
177
+ {:stdout => cmd_stdout, :stderr => cmd_stderr}
178
+ end
179
+
180
+ # Clean-up after a command.
181
+ # @see #run_command
182
+ # @param [String] shell_id The shell id on the remote machine. See #open_shell
183
+ # @param [String] command_id The command id on the remote machine. See #run_command
184
+ # @return [true] This should have more error checking but it just returns true for now.
185
+ def cleanup_command(shell_id, command_id)
186
+ header = {}.merge(resource_uri_cmd).merge(action_signal).merge(selector_shell_id(shell_id))
187
+ # Signal the Command references to terminate (close stdout/stderr)
188
+ resp = invoke("#{NS_WIN_SHELL}:Signal", {:soap_action => :auto, :http_options => nil, :soap_header => header}) do |sig|
189
+ sig.set_attr('CommandId', command_id)
190
+ sig.add("#{NS_WIN_SHELL}:Code",'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/signal/terminate')
191
+ end
192
+ true
193
+ end
194
+
195
+ # Close the shell
196
+ # @param [String] shell_id The shell id on the remote machine. See #open_shell
197
+ # @return [true] This should have more error checking but it just returns true for now.
198
+ def close_shell(shell_id)
199
+ header = {}.merge(resource_uri_cmd).merge(action_delete).merge(selector_shell_id(shell_id))
200
+ # Delete the Shell reference
201
+ resp = invoke(:nil_body, {:soap_action => nil, :soap_body => true, :http_options => nil, :soap_header => header})
202
+ true
203
+ end
204
+
205
+ # Run a Powershell script that resides on the local box.
206
+ # @param [String] script_file The string representing the path to a Powershell script
207
+ # @return [Hash] :stdout and :stderr
208
+ def run_powershell_script(script_file)
209
+ script = File.read(script_file)
210
+ script = script.chars.to_a.join("\x00").chomp.encode('ASCII-8BIT')
211
+ script = Base64.strict_encode64(script)
212
+
213
+ shell_id = open_shell
214
+ command_id = run_command(shell_id, "powershell -encodedCommand #{script}")
215
+ command_output = get_command_output(shell_id, command_id)
216
+ cleanup_command(shell_id, command_id)
217
+ close_shell(shell_id)
218
+ command_output
219
+ end
220
+
221
+
222
+ # Run a WQL Query
223
+ # @see http://msdn.microsoft.com/en-us/library/aa394606(VS.85).aspx
224
+ # @param [String] wql The WQL query
225
+ # @return [Array<Hash>] Returns an array of Hashes that contain the key/value pairs returned from the query.
226
+ def run_wql(wql)
227
+ header = {}.merge(resource_uri_wmi).merge(action_enumerate)
228
+
229
+ begin
230
+ resp = invoke("#{NS_ENUM}:Enumerate", {:soap_action => :auto, :http_options => nil, :soap_header => header}) do |enum|
231
+ enum.add("#{NS_WSMAN_DMTF}:OptimizeEnumeration")
232
+ enum.add("#{NS_WSMAN_DMTF}:MaxElements",'32000')
233
+ mattr = nil
234
+ enum.add("#{NS_WSMAN_DMTF}:Filter", wql) do |filt|
235
+ filt.set_attr('Dialect','http://schemas.microsoft.com/wbem/wsman/1/WQL')
236
+ end
237
+ end
238
+ rescue Handsoap::Fault => e
239
+ raise WinRMWebServiceError, e.reason
240
+ end
241
+
242
+ query_response = []
243
+ (resp/"//#{NS_ENUM}:EnumerateResponse//#{NS_WSMAN_DMTF}:Items/*").each do |i|
244
+ qitem = {}
245
+ (i/'*').each do |si|
246
+ qitem[si.node_name] = si.to_s
247
+ end
248
+ query_response << qitem
249
+ end
250
+ query_response
251
+ end
252
+
253
+
254
+ # To create an empty body set :soap_body => true in the invoke options and set the action to :nil_body
255
+ def iterate_hash_array(element, hash_array)
256
+ add_hierarchy!(element, hash_array, nil) unless hash_array.key?(:nil_body)
257
+ end
258
+
259
+
260
+ protected
261
+
262
+ # Add a hierarchy of elements from hash data
263
+ # @example Hash to XML
264
+ # {:this => {:text =>'that'},'top' => {:id => '32fss', :text => 'TestText', {'middle' => 'bottom'}}}
265
+ # becomes...
266
+ # <this>that</this>
267
+ # <top Id='32fss'>
268
+ # TestText
269
+ # <middle>bottom</middle>
270
+ # </top>
271
+ def add_hierarchy!(node, e_hash, prefix = NS_ADDRESSING)
272
+ prefix << ":" unless prefix.nil?
273
+ e_hash.each_pair do |k,v|
274
+ name = (k.is_a?(Symbol) && k != :text) ? k.to_s.camel_case : k
275
+ if v.is_a? Hash
276
+ node.add("#{prefix}#{name}", v[:text]) do |n|
277
+ add_hierarchy!(n, v, prefix)
278
+ end
279
+ elsif v.is_a? Array
280
+ node.add("#{prefix}#{name}") do |n|
281
+ v.each do |i|
282
+ add_hierarchy!(n, i, prefix)
283
+ end
284
+ end
285
+ else
286
+ node.set_attr(name, v) unless k == :text
287
+ end
288
+ end
289
+ end
290
+
291
+
292
+ # Private Methods (Builders and Parsers)
293
+ private
294
+
295
+ def build!(node, opts = {}, &block)
296
+ #EwsBuilder.new(node, opts, &block)
297
+ end
298
+
299
+ def parse!(response, opts = {})
300
+ return response if @@raw_soap
301
+ #EwsParser.new(response).parse(opts)
302
+ end
303
+
304
+
305
+ # Helper methods for SOAP Headers
306
+
307
+ def resource_uri_cmd
308
+ {"#{NS_WSMAN_DMTF}:ResourceURI" => {'mustUnderstand' => 'true', :text => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd'}}
309
+ end
310
+
311
+ def resource_uri_wmi(namespace = 'root/cimv2/*')
312
+ {"#{NS_WSMAN_DMTF}:ResourceURI" => {'mustUnderstand' => 'true', :text => "http://schemas.microsoft.com/wbem/wsman/1/wmi/#{namespace}"}}
313
+ end
314
+
315
+ def action_create
316
+ {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => 'true', :text => 'http://schemas.xmlsoap.org/ws/2004/09/transfer/Create'}}
317
+ end
318
+
319
+ def action_delete
320
+ {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => 'true', :text => 'http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete'}}
321
+ end
322
+
323
+ def action_command
324
+ {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => 'true', :text => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Command'}}
325
+ end
326
+
327
+ def action_receive
328
+ {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => 'true', :text => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive'}}
329
+ end
330
+
331
+ def action_signal
332
+ {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => 'true', :text => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Signal'}}
333
+ end
334
+
335
+ def action_enumerate
336
+ {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => 'true', :text => 'http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate'}}
337
+ end
338
+
339
+ def selector_shell_id(shell_id)
340
+ {"#{NS_WSMAN_DMTF}:SelectorSet" => {"#{NS_WSMAN_DMTF}:Selector" => {:name => 'ShellId', :text => shell_id}}}
341
+ end
342
+
343
+ end # class WinRMWebService
344
+ end # module SOAP
345
+ end # WinRM
data/lib/winrm.rb ADDED
@@ -0,0 +1,89 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of WinRM.
6
+ #
7
+ # WinRM is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # WinRM is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with WinRM. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+
21
+ # We only what one instance of this class so include Singleton
22
+ require 'singleton'
23
+ require 'date'
24
+ require 'base64'
25
+ require 'uuid'
26
+ require 'kconv'
27
+
28
+ # Class Extensions
29
+ require 'extensions/string'
30
+
31
+ # Load the backend SOAP infrastructure. Today this is Handsoap.
32
+ require 'soap/soap_provider'
33
+
34
+
35
+ module WinRM
36
+ class WinRM
37
+ include Singleton
38
+
39
+ attr_reader :winrm
40
+
41
+ # Set the endpoint for WinRM Web Services.
42
+ # @param [String] endpoint The URL of the endpoint.
43
+ # https://myserver:5986/wsman
44
+ # @param [Integer] version The SOAP version to use. This defaults to 1
45
+ # and you should not need to pass this parameter.
46
+ def self.endpoint=(endpoint, version = 2)
47
+ @@endpoint = endpoint
48
+ SOAP::WinRMWebService.endpoint(:uri => endpoint, :version => version)
49
+ end
50
+
51
+ # Fetch the current endpoint
52
+ def self.endpoint
53
+ @@endpoint
54
+ end
55
+
56
+ # Set the SOAP username and password.
57
+ # @param [String] user The user name
58
+ # @param [String] pass The password
59
+ def self.set_auth(user,pass)
60
+ @@user = user
61
+ SOAP::WinRMWebService.set_auth(user,pass)
62
+ end
63
+
64
+ # Set the http driver that the SOAP back-end will use.
65
+ # @param [Symbol] driver The HTTP driver. Available drivers:
66
+ # :curb, :net_http, :http_client(Default)
67
+ def self.set_http_driver(driver)
68
+ Handsoap.http_driver = driver
69
+ end
70
+
71
+ def initialize
72
+ @winrm = SOAP::WinRMWebService.new
73
+ end
74
+
75
+ # Run a Powershell script
76
+ # @see WinRM::SOAP::WinRMWebService#run_powershell_script
77
+ def powershell(script_file)
78
+ @winrm.run_powershell_script(script_file)
79
+ end
80
+
81
+ # Run a WQL Query
82
+ # @see WinRM::SOAP::WinRMWebService#run_wql
83
+ # @see http://msdn.microsoft.com/en-us/library/aa394606(VS.85).aspx
84
+ def wql(wql)
85
+ @winrm.run_wql(wql)
86
+ end
87
+
88
+ end # class WinRM
89
+ end
data/preamble ADDED
@@ -0,0 +1,19 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of WinRM.
6
+ #
7
+ # WinRM is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # WinRM is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with WinRM. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################