winrm 1.0.0rc4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Rakefile +9 -38
- data/VERSION +1 -1
- data/lib/winrm/exceptions/exceptions.rb +3 -0
- data/lib/winrm/http/transport.rb +7 -5
- data/lib/winrm/soap_provider.rb +2 -2
- data/lib/winrm/winrm_service.rb +67 -25
- data/test/.rspec +2 -0
- data/test/spec/cmd_spec.rb +27 -0
- data/test/spec/powershell_spec.rb +14 -0
- data/test/spec/spec_helper.rb +21 -0
- data/test/spec/winrm_primitives_spec.rb +67 -0
- data/test/spec/wql_spec.rb +12 -0
- data/winrm.gemspec +6 -6
- metadata +24 -20
- data/test/spec/powershell_tests.spec +0 -25
- data/test/spec/spec.opts +0 -5
- data/test/spec/wql_tests.spec +0 -24
data/.gitignore
ADDED
data/Rakefile
CHANGED
@@ -1,52 +1,20 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake/clean'
|
3
|
-
require 'rake/gempackagetask'
|
4
3
|
require 'date'
|
5
4
|
|
6
5
|
CLEAN.include("pkg")
|
7
6
|
CLEAN.include("doc")
|
7
|
+
CLEAN.include("*.gem")
|
8
8
|
|
9
|
-
|
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
|
9
|
+
task :default => [:gem]
|
15
10
|
|
16
|
-
|
17
|
-
|
18
|
-
|
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'
|
11
|
+
desc "Build the gem from the gemspec"
|
12
|
+
task :repackage do
|
13
|
+
system "gem build winrm.gemspec"
|
36
14
|
end
|
37
|
-
|
38
|
-
Rake::GemPackageTask.new(GEMSPEC) do |pkg|
|
39
|
-
pkg.need_tar = true
|
40
|
-
end
|
41
|
-
|
42
|
-
task :default => [:buildgem]
|
43
15
|
|
44
16
|
desc "Build the gem without a version change"
|
45
|
-
task :
|
46
|
-
|
47
|
-
desc "Build the gem, but increment the version first"
|
48
|
-
task :newrelease => [:versionup, :clean, :repackage]
|
49
|
-
|
17
|
+
task :gem => [:clean, :repackage]
|
50
18
|
|
51
19
|
desc "Increment the version by 1 minor release"
|
52
20
|
task :versionup do
|
@@ -54,6 +22,9 @@ task :versionup do
|
|
54
22
|
puts "New version: #{ver}"
|
55
23
|
end
|
56
24
|
|
25
|
+
desc "Build the gem, but increment the version first"
|
26
|
+
task :newrelease => [:versionup, :clean, :repackage]
|
27
|
+
|
57
28
|
|
58
29
|
def up_min_version
|
59
30
|
f = File.open('VERSION', 'r+')
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.0
|
data/lib/winrm/http/transport.rb
CHANGED
@@ -11,6 +11,7 @@ module WinRM
|
|
11
11
|
def initialize(endpoint)
|
12
12
|
@endpoint = endpoint.is_a?(String) ? URI.parse(endpoint) : endpoint
|
13
13
|
@httpcli = HTTPClient.new(:agent_name => 'Ruby WinRM Client')
|
14
|
+
@httpcli.receive_timeout = 3600 # Set this to an unreasonable amount for now because WinRM has timeouts
|
14
15
|
end
|
15
16
|
|
16
17
|
def send_request(message)
|
@@ -19,19 +20,17 @@ module WinRM
|
|
19
20
|
if(resp.status == 200)
|
20
21
|
# Version 1.1 of WinRM adds the namespaces in the document instead of the envelope so we have to
|
21
22
|
# add them ourselves here. This should have no affect version 2.
|
22
|
-
doc = Nokogiri::XML(resp.
|
23
|
+
doc = Nokogiri::XML(resp.http_body.content)
|
23
24
|
doc.collect_namespaces.each_pair do |k,v|
|
24
25
|
doc.root.add_namespace((k.split(/:/).last),v) unless doc.namespaces.has_key?(k)
|
25
26
|
end
|
26
27
|
return doc
|
27
28
|
else
|
28
|
-
|
29
|
-
# TODO: raise error
|
29
|
+
raise WinRMHTTPTransportError, "Bad HTTP response returned from server (#{resp.status})."
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
# We'll need this to force basic authentication if desired
|
34
|
-
# TODO: implement this for basic auth needs
|
35
34
|
def basic_auth_only!
|
36
35
|
auths = @httpcli.www_auth.instance_variable_get('@authenticator')
|
37
36
|
auths.delete_if {|i| i.scheme !~ /basic/i}
|
@@ -64,6 +63,9 @@ module WinRM
|
|
64
63
|
# @param [String<optional>] keytab the path to a keytab file if you are using one
|
65
64
|
def initialize(endpoint, realm, service = nil, keytab = nil, opts)
|
66
65
|
super(endpoint)
|
66
|
+
# Remove the GSSAPI auth from HTTPClient because we are doing our own thing
|
67
|
+
auths = @httpcli.www_auth.instance_variable_get('@authenticator')
|
68
|
+
auths.delete_if {|i| i.is_a?(HTTPClient::SSPINegotiateAuth)}
|
67
69
|
service ||= 'HTTP'
|
68
70
|
@service = "#{service}/#{@endpoint.host}@#{realm}"
|
69
71
|
init_krb
|
@@ -92,7 +94,7 @@ Content-Type: application/octet-stream\r
|
|
92
94
|
|
93
95
|
r = @httpcli.post(@endpoint, body, hdr)
|
94
96
|
|
95
|
-
winrm_decrypt(r.
|
97
|
+
winrm_decrypt(r.http_body.content)
|
96
98
|
end
|
97
99
|
|
98
100
|
|
data/lib/winrm/soap_provider.rb
CHANGED
@@ -20,8 +20,7 @@
|
|
20
20
|
|
21
21
|
require 'httpclient'
|
22
22
|
require 'savon/soap/xml'
|
23
|
-
require '
|
24
|
-
require 'gssapi'
|
23
|
+
require 'uuidtools'
|
25
24
|
require 'base64'
|
26
25
|
require 'nokogiri'
|
27
26
|
|
@@ -36,6 +35,7 @@ module WinRM
|
|
36
35
|
NS_SCHEMA_INST ='xsi' # http://www.w3.org/2001/XMLSchema-instance
|
37
36
|
NS_WIN_SHELL ='rsp' # http://schemas.microsoft.com/wbem/wsman/1/windows/shell
|
38
37
|
NS_WSMAN_FAULT = 'f' # http://schemas.microsoft.com/wbem/wsman/1/wsmanfault
|
38
|
+
NS_WSMAN_CONF = 'cfg'# http://schemas.microsoft.com/wbem/wsman/1/config
|
39
39
|
end
|
40
40
|
|
41
41
|
require 'winrm/exceptions/exceptions'
|
data/lib/winrm/winrm_service.rb
CHANGED
@@ -7,7 +7,7 @@ module WinRM
|
|
7
7
|
DEFAULT_MAX_ENV_SIZE = 153600
|
8
8
|
DEFAULT_LOCALE = 'en-US'
|
9
9
|
|
10
|
-
attr_reader :endpoint
|
10
|
+
attr_reader :endpoint, :timeout
|
11
11
|
|
12
12
|
# @param [String,URI] endpoint the WinRM webservice endpoint
|
13
13
|
# @param [Symbol] transport either :kerberos(default)/:ssl/:plaintext
|
@@ -22,6 +22,7 @@ module WinRM
|
|
22
22
|
@locale = DEFAULT_LOCALE
|
23
23
|
case transport
|
24
24
|
when :kerberos
|
25
|
+
require 'gssapi'
|
25
26
|
# TODO: check fo keys and throw error if missing
|
26
27
|
@xfer = HTTP::HttpGSSAPI.new(endpoint, opts[:realm], opts[:service], opts[:keytab], opts)
|
27
28
|
when :plaintext
|
@@ -32,34 +33,64 @@ module WinRM
|
|
32
33
|
end
|
33
34
|
|
34
35
|
# Operation timeout
|
35
|
-
|
36
|
+
# @see http://msdn.microsoft.com/en-us/library/ee916629(v=PROT.13).aspx
|
37
|
+
# @param [Fixnum] sec the number of seconds to set the timeout to. It will be converted to an ISO8601 format.
|
38
|
+
def set_timeout(sec)
|
36
39
|
@timeout = Iso8601Duration.sec_to_dur(sec)
|
37
40
|
end
|
41
|
+
alias :op_timeout :set_timeout
|
38
42
|
|
39
43
|
# Max envelope size
|
40
|
-
|
41
|
-
|
44
|
+
# @see http://msdn.microsoft.com/en-us/library/ee916127(v=PROT.13).aspx
|
45
|
+
# @param [Fixnum] byte_sz the max size in bytes to allow for the response
|
46
|
+
def max_env_size(byte_sz)
|
47
|
+
@max_env_sz = byte_sz
|
42
48
|
end
|
43
49
|
|
44
|
-
#
|
50
|
+
# Set the locale
|
51
|
+
# @see http://msdn.microsoft.com/en-us/library/gg567404(v=PROT.13).aspx
|
52
|
+
# @param [String] locale the locale to set for future messages
|
45
53
|
def locale(locale)
|
46
54
|
@locale = locale
|
47
55
|
end
|
48
56
|
|
49
57
|
# Create a Shell on the destination host
|
50
|
-
# @param [
|
51
|
-
# @
|
58
|
+
# @param [Hash<optional>] shell_opts additional shell options you can pass
|
59
|
+
# @option shell_opts [String] :i_stream Which input stream to open. Leave this alone unless you know what you're doing (default: stdin)
|
60
|
+
# @option shell_opts [String] :o_stream Which output stream to open. Leave this alone unless you know what you're doing (default: stdout stderr)
|
61
|
+
# @option shell_opts [String] :working_directory the directory to create the shell in
|
62
|
+
# @option shell_opts [Hash] :env_vars environment variables to set for the shell. For instance;
|
63
|
+
# :env_vars => {:myvar1 => 'val1', :myvar2 => 'var2'}
|
52
64
|
# @return [String] The ShellId from the SOAP response. This is our open shell instance on the remote machine.
|
53
|
-
def open_shell(
|
65
|
+
def open_shell(shell_opts = {})
|
66
|
+
i_stream = shell_opts.has_key?(:i_stream) ? shell_opts[:i_stream] : 'stdin'
|
67
|
+
o_stream = shell_opts.has_key?(:o_stream) ? shell_opts[:o_stream] : 'stdout stderr'
|
68
|
+
codepage = shell_opts.has_key?(:codepage) ? shell_opts[:codepage] : 437
|
69
|
+
noprofile = shell_opts.has_key?(:noprofile) ? shell_opts[:noprofile] : 'FALSE'
|
54
70
|
s = Savon::SOAP::XML.new
|
55
71
|
s.version = 2
|
56
72
|
s.namespaces.merge!(namespaces)
|
57
|
-
h_opts = { "#{NS_WSMAN_DMTF}:OptionSet" => { "#{NS_WSMAN_DMTF}:Option" => [
|
73
|
+
h_opts = { "#{NS_WSMAN_DMTF}:OptionSet" => { "#{NS_WSMAN_DMTF}:Option" => [noprofile, codepage],
|
58
74
|
:attributes! => {"#{NS_WSMAN_DMTF}:Option" => {'Name' => ['WINRS_NOPROFILE','WINRS_CODEPAGE']}}}}
|
59
75
|
s.header.merge!(merge_headers(header,resource_uri_cmd,action_create,h_opts))
|
60
76
|
s.input = "#{NS_WIN_SHELL}:Shell"
|
61
|
-
s.body = {
|
62
|
-
"#{NS_WIN_SHELL}:
|
77
|
+
s.body = {
|
78
|
+
"#{NS_WIN_SHELL}:InputStreams" => i_stream,
|
79
|
+
"#{NS_WIN_SHELL}:OutputStreams" => o_stream
|
80
|
+
}
|
81
|
+
s.body["#{NS_WIN_SHELL}:WorkingDirectory"] = shell_opts[:working_directory] if shell_opts.has_key?(:working_directory)
|
82
|
+
# TODO: research Lifetime a bit more: http://msdn.microsoft.com/en-us/library/cc251546(v=PROT.13).aspx
|
83
|
+
#s.body["#{NS_WIN_SHELL}:Lifetime"] = Iso8601Duration.sec_to_dur(shell_opts[:lifetime]) if(shell_opts.has_key?(:lifetime) && shell_opts[:lifetime].is_a?(Fixnum))
|
84
|
+
# @todo make it so the input is given in milliseconds and converted to xs:duration
|
85
|
+
s.body["#{NS_WIN_SHELL}:IdleTimeOut"] = shell_opts[:idle_timeout] if(shell_opts.has_key?(:idle_timeout) && shell_opts[:idle_timeout].is_a?(String))
|
86
|
+
if(shell_opts.has_key?(:env_vars) && shell_opts[:env_vars].is_a?(Hash))
|
87
|
+
keys = shell_opts[:env_vars].keys
|
88
|
+
vals = shell_opts[:env_vars].values
|
89
|
+
s.body["#{NS_WIN_SHELL}:Environment"] = {
|
90
|
+
"#{NS_WIN_SHELL}:Variable" => vals,
|
91
|
+
:attributes! => {"#{NS_WIN_SHELL}:Variable" => {'Name' => keys}}
|
92
|
+
}
|
93
|
+
end
|
63
94
|
|
64
95
|
resp = send_message(s.to_xml)
|
65
96
|
(resp/"//*[@Name='ShellId']").text
|
@@ -70,12 +101,14 @@ module WinRM
|
|
70
101
|
# @param [String] command The command to run on the remote machine
|
71
102
|
# @param [Array<String>] arguments An array of arguments for this command
|
72
103
|
# @return [String] The CommandId from the SOAP response. This is the ID we need to query in order to get output.
|
73
|
-
def run_command(shell_id, command, arguments = [])
|
104
|
+
def run_command(shell_id, command, arguments = [], cmd_opts = {})
|
105
|
+
consolemode = cmd_opts.has_key?(:console_mode_stdin) ? cmd_opts[:console_mode_stdin] : 'TRUE'
|
106
|
+
skipcmd = cmd_opts.has_key?(:skip_cmd_shell) ? cmd_opts[:skip_cmd_shell] : 'FALSE'
|
74
107
|
s = Savon::SOAP::XML.new
|
75
108
|
s.version = 2
|
76
109
|
s.namespaces.merge!(namespaces)
|
77
110
|
h_opts = { "#{NS_WSMAN_DMTF}:OptionSet" => {
|
78
|
-
"#{NS_WSMAN_DMTF}:Option" => [
|
111
|
+
"#{NS_WSMAN_DMTF}:Option" => [consolemode, skipcmd],
|
79
112
|
:attributes! => {"#{NS_WSMAN_DMTF}:Option" => {'Name' => ['WINRS_CONSOLEMODE_STDIN','WINRS_SKIP_CMD_SHELL']}}}
|
80
113
|
}
|
81
114
|
s.header.merge!(merge_headers(header,resource_uri_cmd,action_command,h_opts,selector_shell_id(shell_id)))
|
@@ -177,9 +210,7 @@ module WinRM
|
|
177
210
|
end
|
178
211
|
|
179
212
|
resp = send_message(s.to_xml)
|
180
|
-
|
181
|
-
resp.remove_namespaces!
|
182
|
-
(resp/"//Fault").empty?
|
213
|
+
true
|
183
214
|
end
|
184
215
|
|
185
216
|
# Run a CMD command
|
@@ -219,6 +250,7 @@ module WinRM
|
|
219
250
|
close_shell(shell_id)
|
220
251
|
command_output
|
221
252
|
end
|
253
|
+
alias :powershell :run_powershell_script
|
222
254
|
|
223
255
|
|
224
256
|
# Run a WQL Query
|
@@ -250,6 +282,7 @@ module WinRM
|
|
250
282
|
end
|
251
283
|
items
|
252
284
|
end
|
285
|
+
alias :wql :run_wql
|
253
286
|
|
254
287
|
|
255
288
|
private
|
@@ -261,7 +294,9 @@ module WinRM
|
|
261
294
|
'xmlns:x' => 'http://schemas.xmlsoap.org/ws/2004/09/transfer',
|
262
295
|
'xmlns:w' => 'http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd',
|
263
296
|
'xmlns:p' => 'http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd',
|
264
|
-
'xmlns:rsp' => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell'
|
297
|
+
'xmlns:rsp' => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell',
|
298
|
+
'xmlns:cfg' => 'http://schemas.microsoft.com/wbem/wsman/1/config',
|
299
|
+
}
|
265
300
|
end
|
266
301
|
|
267
302
|
def header
|
@@ -270,9 +305,10 @@ module WinRM
|
|
270
305
|
"#{NS_ADDRESSING}:Address" => 'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous',
|
271
306
|
:attributes! => {"#{NS_ADDRESSING}:Address" => {'mustUnderstand' => true}}},
|
272
307
|
"#{NS_WSMAN_DMTF}:MaxEnvelopeSize" => @max_env_sz,
|
273
|
-
"#{NS_ADDRESSING}:MessageID" => "uuid:#{UUID.
|
308
|
+
"#{NS_ADDRESSING}:MessageID" => "uuid:#{UUIDTools::UUID.random_create.to_s.upcase}",
|
274
309
|
"#{NS_WSMAN_DMTF}:Locale/" => '',
|
275
310
|
"#{NS_WSMAN_MSFT}:DataLocale/" => '',
|
311
|
+
#"#{NS_WSMAN_CONF}:MaxTimeoutms" => 600, #TODO: research this a bit http://msdn.microsoft.com/en-us/library/cc251561(v=PROT.13).aspx
|
276
312
|
"#{NS_WSMAN_DMTF}:OperationTimeout" => @timeout,
|
277
313
|
:attributes! => {
|
278
314
|
"#{NS_WSMAN_DMTF}:MaxEnvelopeSize" => {'mustUnderstand' => true},
|
@@ -296,13 +332,19 @@ module WinRM
|
|
296
332
|
def send_message(message)
|
297
333
|
resp = @xfer.send_request(message)
|
298
334
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
335
|
+
begin
|
336
|
+
errors = resp/"//#{NS_SOAP_ENV}:Body/#{NS_SOAP_ENV}:Fault/*"
|
337
|
+
if errors.empty?
|
338
|
+
return resp
|
339
|
+
else
|
340
|
+
resp.root.add_namespace(NS_WSMAN_FAULT,'http://schemas.microsoft.com/wbem/wsman/1/wsmanfault')
|
341
|
+
fault = (errors/"//#{NS_WSMAN_FAULT}:WSManFault").first
|
342
|
+
raise WinRMWSManFault, "[WSMAN ERROR CODE: #{fault['Code']}]: #{fault.text}"
|
343
|
+
end
|
344
|
+
# Sometimes a blank response is returned and it will throw this error when the XPath is evaluated for Fault
|
345
|
+
# The returned string will be '<?xml version="1.0"?>\n' in these cases
|
346
|
+
rescue Nokogiri::XML::XPath::SyntaxError => e
|
347
|
+
raise WinRMWebServiceError, "Bad SOAP Packet returned. Sometimes a retry will solve this error."
|
306
348
|
end
|
307
349
|
end
|
308
350
|
|
data/test/.rspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Test remote WQL features via WinRM" do
|
4
|
+
before(:all) do
|
5
|
+
@winrm = winrm_connection
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should run a CMD command string' do
|
9
|
+
output = @winrm.run_cmd('ipconfig /all')
|
10
|
+
output[:exitcode].should == 0
|
11
|
+
output[:data].should_not be_empty
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should run a CMD command with proper arguments' do
|
15
|
+
output = @winrm.run_cmd('ipconfig', %w{/all})
|
16
|
+
output[:exitcode].should == 0
|
17
|
+
output[:data].should_not be_empty
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should run a CMD command with block' do
|
21
|
+
outvar = ''
|
22
|
+
@winrm.run_cmd('ipconfig', %w{/all}) do |stdout, stderr|
|
23
|
+
outvar << stdout
|
24
|
+
end
|
25
|
+
outvar.should =~ /Windows IP Configuration/
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Test remote Powershell features via WinRM" do
|
4
|
+
before(:all) do
|
5
|
+
@winrm = winrm_connection
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should run a test Powershell script' do
|
9
|
+
ps_file = File.open('spec/test.ps1', 'r+')
|
10
|
+
output = @winrm.run_powershell_script(File.open('spec/test.ps1'))
|
11
|
+
ps_file.close
|
12
|
+
output[:exitcode].should == 0
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
$: << File.dirname(__FILE__) + '/../../lib/'
|
2
|
+
require 'winrm'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module ConnectionHelper
|
6
|
+
# To run this test put a file called 'creds.json' in this directory with the following format:
|
7
|
+
# {"user":"myuser","pass":"mypass","endpoint":"http://mysys.com/wsman","realm":"MY.REALM"}
|
8
|
+
CREDS_FILE='spec/creds.json'
|
9
|
+
|
10
|
+
def winrm_connection
|
11
|
+
creds = JSON.load(File.open(CREDS_FILE,'r'))
|
12
|
+
winrm = WinRM::WinRMWebService.new(creds['endpoint'], :kerberos, :realm => creds['realm'])
|
13
|
+
#winrm = WinRM::WinRMWebService.new(creds['endpoint'], :plaintext, :user => creds['user'], :pass => creds['pass'])
|
14
|
+
#winrm = WinRM::WinRMWebService.new(creds['endpoint'], :plaintext, :user => creds['user'], :pass => creds['pass'], :basic_auth_only => true)
|
15
|
+
winrm
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
RSpec.configure do |config|
|
20
|
+
config.include(ConnectionHelper)
|
21
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Test WinRM primitive methods" do
|
4
|
+
before(:all) do
|
5
|
+
@winrm = winrm_connection
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should #open_shell and #close_shell' do
|
9
|
+
sid = @winrm.open_shell
|
10
|
+
# match a UUID
|
11
|
+
sid.should =~ /^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/
|
12
|
+
@winrm.close_shell(sid).should be_true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should #run_command and #cleanup_command' do
|
16
|
+
sid = @winrm.open_shell
|
17
|
+
|
18
|
+
cmd_id = @winrm.run_command(sid, 'ipconfig', %w{/all})
|
19
|
+
cmd_id.should =~ /^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/
|
20
|
+
|
21
|
+
@winrm.cleanup_command(sid, cmd_id).should be_true
|
22
|
+
@winrm.close_shell(sid)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should #get_command_output' do
|
26
|
+
sid = @winrm.open_shell
|
27
|
+
cmd_id = @winrm.run_command(sid, 'ipconfig', %w{/all})
|
28
|
+
|
29
|
+
output = @winrm.get_command_output(sid, cmd_id)
|
30
|
+
output[:exitcode].should == 0
|
31
|
+
output[:data].should_not be_empty
|
32
|
+
|
33
|
+
@winrm.cleanup_command(sid, cmd_id)
|
34
|
+
@winrm.close_shell(sid)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should #get_command_output with a block' do
|
38
|
+
sid = @winrm.open_shell
|
39
|
+
cmd_id = @winrm.run_command(sid, 'ipconfig', %w{/all})
|
40
|
+
|
41
|
+
outvar = ''
|
42
|
+
@winrm.get_command_output(sid, cmd_id) do |stdout, stderr|
|
43
|
+
outvar << stdout
|
44
|
+
end
|
45
|
+
outvar.should =~ /Windows IP Configuration/
|
46
|
+
|
47
|
+
@winrm.cleanup_command(sid, cmd_id)
|
48
|
+
@winrm.close_shell(sid)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should set #op_timeout' do
|
52
|
+
@winrm.op_timeout(120).should == 'PT2M0S'
|
53
|
+
@winrm.op_timeout(1202).should == 'PT20M2S'
|
54
|
+
@winrm.op_timeout(86400).should == 'PT24H0S'
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should set #max_env_size' do
|
58
|
+
@winrm.max_env_size(153600 * 4)
|
59
|
+
@winrm.instance_variable_get('@max_env_sz').should == 614400
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should set #locale' do
|
63
|
+
@winrm.locale('en-ca')
|
64
|
+
@winrm.instance_variable_get('@locale').should == 'en-ca'
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Test remote WQL features via WinRM" do
|
4
|
+
before(:all) do
|
5
|
+
@winrm = winrm_connection
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should run a WQL query against Win32_Service' do
|
9
|
+
output = @winrm.run_wql('select Name,Status from Win32_Service')
|
10
|
+
output.should_not be_empty
|
11
|
+
end
|
12
|
+
end
|
data/winrm.gemspec
CHANGED
@@ -24,10 +24,10 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.extra_rdoc_files = %w(README COPYING.txt)
|
25
25
|
|
26
26
|
s.required_ruby_version = '>= 1.9.0'
|
27
|
-
s.add_runtime_dependency 'gssapi', '
|
28
|
-
s.add_runtime_dependency 'nokogiri'
|
29
|
-
s.add_runtime_dependency 'httpclient'
|
30
|
-
s.add_runtime_dependency 'rubyntlm'
|
31
|
-
s.add_runtime_dependency '
|
32
|
-
s.add_runtime_dependency 'savon'
|
27
|
+
s.add_runtime_dependency 'gssapi', '~> 0.1.5'
|
28
|
+
s.add_runtime_dependency 'nokogiri', '~> 1.4.4'
|
29
|
+
s.add_runtime_dependency 'httpclient', '~> 2.2.0.2'
|
30
|
+
s.add_runtime_dependency 'rubyntlm', '~> 0.1.1'
|
31
|
+
s.add_runtime_dependency 'uuidtools', '~> 2.1.2'
|
32
|
+
s.add_runtime_dependency 'savon', '~> 0.9.1'
|
33
33
|
end
|
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: winrm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
version: 1.0.
|
4
|
+
prerelease:
|
5
|
+
version: 1.0.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Dan Wanek
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-04-29 00:00:00 -05:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
requirement: &id001 !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
|
-
- -
|
22
|
+
- - ~>
|
23
23
|
- !ruby/object:Gem::Version
|
24
24
|
version: 0.1.5
|
25
25
|
type: :runtime
|
@@ -30,9 +30,9 @@ dependencies:
|
|
30
30
|
requirement: &id002 !ruby/object:Gem::Requirement
|
31
31
|
none: false
|
32
32
|
requirements:
|
33
|
-
- -
|
33
|
+
- - ~>
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version:
|
35
|
+
version: 1.4.4
|
36
36
|
type: :runtime
|
37
37
|
version_requirements: *id002
|
38
38
|
- !ruby/object:Gem::Dependency
|
@@ -41,9 +41,9 @@ dependencies:
|
|
41
41
|
requirement: &id003 !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
|
-
- -
|
44
|
+
- - ~>
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
46
|
+
version: 2.2.0.2
|
47
47
|
type: :runtime
|
48
48
|
version_requirements: *id003
|
49
49
|
- !ruby/object:Gem::Dependency
|
@@ -52,20 +52,20 @@ dependencies:
|
|
52
52
|
requirement: &id004 !ruby/object:Gem::Requirement
|
53
53
|
none: false
|
54
54
|
requirements:
|
55
|
-
- -
|
55
|
+
- - ~>
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version:
|
57
|
+
version: 0.1.1
|
58
58
|
type: :runtime
|
59
59
|
version_requirements: *id004
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
|
-
name:
|
61
|
+
name: uuidtools
|
62
62
|
prerelease: false
|
63
63
|
requirement: &id005 !ruby/object:Gem::Requirement
|
64
64
|
none: false
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 2.1.2
|
69
69
|
type: :runtime
|
70
70
|
version_requirements: *id005
|
71
71
|
- !ruby/object:Gem::Dependency
|
@@ -74,9 +74,9 @@ dependencies:
|
|
74
74
|
requirement: &id006 !ruby/object:Gem::Requirement
|
75
75
|
none: false
|
76
76
|
requirements:
|
77
|
-
- -
|
77
|
+
- - ~>
|
78
78
|
- !ruby/object:Gem::Version
|
79
|
-
version:
|
79
|
+
version: 0.9.1
|
80
80
|
type: :runtime
|
81
81
|
version_requirements: *id006
|
82
82
|
description: " Ruby library for Windows Remote Management\n"
|
@@ -89,6 +89,7 @@ extra_rdoc_files:
|
|
89
89
|
- README
|
90
90
|
- COPYING.txt
|
91
91
|
files:
|
92
|
+
- .gitignore
|
92
93
|
- COPYING.txt
|
93
94
|
- README
|
94
95
|
- Rakefile
|
@@ -100,10 +101,13 @@ files:
|
|
100
101
|
- lib/winrm/soap_provider.rb
|
101
102
|
- lib/winrm/winrm_service.rb
|
102
103
|
- preamble
|
103
|
-
- test
|
104
|
-
- test/spec/
|
104
|
+
- test/.rspec
|
105
|
+
- test/spec/cmd_spec.rb
|
106
|
+
- test/spec/powershell_spec.rb
|
107
|
+
- test/spec/spec_helper.rb
|
105
108
|
- test/spec/test.ps1
|
106
|
-
- test/spec/
|
109
|
+
- test/spec/winrm_primitives_spec.rb
|
110
|
+
- test/spec/wql_spec.rb
|
107
111
|
- winrm.gemspec
|
108
112
|
has_rdoc: true
|
109
113
|
homepage: http://github.com/zenchild/WinRM
|
@@ -126,9 +130,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
126
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
131
|
none: false
|
128
132
|
requirements:
|
129
|
-
- - "
|
133
|
+
- - ">="
|
130
134
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
135
|
+
version: "0"
|
132
136
|
requirements: []
|
133
137
|
|
134
138
|
rubyforge_project:
|
@@ -1,25 +0,0 @@
|
|
1
|
-
$: << File.dirname(__FILE__) + '/../../lib/'
|
2
|
-
require 'kconv'
|
3
|
-
require 'winrm'
|
4
|
-
require 'json'
|
5
|
-
|
6
|
-
# To run this test put a file called 'creds.json' in this directory with the following format:
|
7
|
-
# {"user":"myuser","pass":"mypass","endpoint":"http://mysys.com/wsman"}
|
8
|
-
|
9
|
-
|
10
|
-
describe "Test remote Powershell features via WinRM" do
|
11
|
-
before(:all) do
|
12
|
-
creds = JSON.load(File.open('spec/creds.json','r'))
|
13
|
-
WinRM::WinRM.endpoint = creds['endpoint']
|
14
|
-
WinRM::WinRM.set_auth(creds['user'],creds['pass'])
|
15
|
-
WinRM::WinRM.set_ca_trust_path('/etc/ssl/certs')
|
16
|
-
WinRM::WinRM.instance
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'should run a test Powershell script' do
|
20
|
-
winrm = WinRM::WinRM.instance
|
21
|
-
output = winrm.powershell('spec/test.ps1')
|
22
|
-
output[:exitcode].should eql(0)
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
data/test/spec/spec.opts
DELETED
data/test/spec/wql_tests.spec
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
$: << File.dirname(__FILE__) + '/../../lib/'
|
2
|
-
require 'kconv'
|
3
|
-
require 'winrm'
|
4
|
-
require 'json'
|
5
|
-
|
6
|
-
# To run this test put a file called 'creds.json' in this directory with the following format:
|
7
|
-
# {"user":"myuser","pass":"mypass","endpoint":"http://mysys.com/wsman"}
|
8
|
-
|
9
|
-
|
10
|
-
describe "Test remote WQL features via WinRM" do
|
11
|
-
before(:all) do
|
12
|
-
creds = JSON.load(File.open('spec/creds.json','r'))
|
13
|
-
WinRM::WinRM.endpoint = creds['endpoint']
|
14
|
-
WinRM::WinRM.set_auth(creds['user'],creds['pass'])
|
15
|
-
WinRM::WinRM.set_ca_trust_path('/etc/ssl/certs')
|
16
|
-
WinRM::WinRM.instance
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'should run a WQL query against Win32_Service' do
|
20
|
-
winrm = WinRM::WinRM.instance
|
21
|
-
output = winrm.wql('select Name,Status from Win32_Service')
|
22
|
-
output.should_not be_empty
|
23
|
-
end
|
24
|
-
end
|