winrm 1.0.0rc4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|