winrm 0.0.6 → 1.0.0rc1

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.
@@ -0,0 +1,356 @@
1
+ module WinRM
2
+ # This is the main class that does the SOAP request/response logic. There are a few helper classes, but pretty
3
+ # much everything comes through here first.
4
+ class WinRMWebService
5
+
6
+ DEFAULT_TIMEOUT = 'PT60S'
7
+ DEFAULT_MAX_ENV_SIZE = 153600
8
+ DEFAULT_LOCALE = 'en-US'
9
+
10
+ # @param [String,URI] endpoint the WinRM webservice endpoint
11
+ # @param [Symbol] transport either :kerberos(default)/:ssl/:plaintext
12
+ # @param [Hash] opts Misc opts for the various transports.
13
+ # @see WinRM::HTTP::HttpTransport
14
+ # @see WinRM::HTTP::HttpGSSAPI
15
+ # @see WinRM::HTTP::HttpSSL
16
+ def initialize(endpoint, transport = :kerberos, opts = {})
17
+ @timeout = DEFAULT_TIMEOUT
18
+ @max_env_sz = DEFAULT_MAX_ENV_SIZE
19
+ @locale = DEFAULT_LOCALE
20
+ case transport
21
+ when :kerberos
22
+ # TODO: check fo keys and throw error if missing
23
+ @xfer = HTTP::HttpGSSAPI.new(endpoint, opts[:realm], opts[:service], opts[:keytab])
24
+ when :plaintext
25
+ @xfer = HTTP::HttpPlaintext.new(endpoint, opts[:user], opts[:pass])
26
+ when :ssl
27
+ @xfer = HTTP::HttpSSL.new(endpoint, opts[:user], opts[:pass], opts[:ca_trust_path])
28
+ end
29
+ end
30
+
31
+ # Operation timeout
32
+ def op_timeout(sec)
33
+ @timeout = Iso8601Duration.sec_to_dur(sec)
34
+ end
35
+
36
+ # Max envelope size
37
+ def max_env_size(sz)
38
+ @max_env_sz = sz
39
+ end
40
+
41
+ # Default locale
42
+ def locale(locale)
43
+ @locale = locale
44
+ end
45
+
46
+ # Create a Shell on the destination host
47
+ # @param [String<optional>] i_stream Which input stream to open. Leave this alone unless you know what you're doing
48
+ # @param [String<optional>] o_stream Which output stream to open. Leave this alone unless you know what you're doing
49
+ # @return [String] The ShellId from the SOAP response. This is our open shell instance on the remote machine.
50
+ def open_shell(i_stream = 'stdin', o_stream = 'stdout stderr')
51
+ s = Savon::SOAP::XML.new
52
+ s.version = 2
53
+ s.namespaces.merge!(namespaces)
54
+ h_opts = { "#{NS_WSMAN_DMTF}:OptionSet" => { "#{NS_WSMAN_DMTF}:Option" => ['FALSE',437],
55
+ :attributes! => {"#{NS_WSMAN_DMTF}:Option" => {'Name' => ['WINRS_NOPROFILE','WINRS_CODEPAGE']}}}}
56
+ s.header.merge!(merge_headers(header,resource_uri_cmd,action_create,h_opts))
57
+ s.input = "#{NS_WIN_SHELL}:Shell"
58
+ s.body = { "#{NS_WIN_SHELL}:InputStreams" => i_stream,
59
+ "#{NS_WIN_SHELL}:OutputStreams" => o_stream}
60
+
61
+ resp = send_message(s.to_xml)
62
+ (resp/"//*[@Name='ShellId']").text
63
+ end
64
+
65
+ # Run a command on a machine with an open shell
66
+ # @param [String] shell_id The shell id on the remote machine. See #open_shell
67
+ # @param [String] command The command to run on the remote machine
68
+ # @return [String] The CommandId from the SOAP response. This is the ID we need to query in order to get output.
69
+ def run_command(shell_id, command)
70
+ s = Savon::SOAP::XML.new
71
+ s.version = 2
72
+ s.namespaces.merge!(namespaces)
73
+ h_opts = { "#{NS_WSMAN_DMTF}:OptionSet" => {
74
+ "#{NS_WSMAN_DMTF}:Option" => ['TRUE','FALSE'],
75
+ :attributes! => {"#{NS_WSMAN_DMTF}:Option" => {'Name' => ['WINRS_CONSOLEMODE_STDIN','WINRS_SKIP_CMD_SHELL']}}}
76
+ }
77
+ s.header.merge!(merge_headers(header,resource_uri_cmd,action_command,h_opts,selector_shell_id(shell_id)))
78
+ s.input = "#{NS_WIN_SHELL}:CommandLine"
79
+ s.body = { "#{NS_WIN_SHELL}:Command" => "\"#{command}\"" }
80
+
81
+ resp = send_message(s.to_xml)
82
+ (resp/"//#{NS_WIN_SHELL}:CommandId").text
83
+ end
84
+
85
+ # Get the Output of the given shell and command
86
+ # @param [String] shell_id The shell id on the remote machine. See #open_shell
87
+ # @param [String] command_id The command id on the remote machine. See #run_command
88
+ # @return [Hash] Returns a Hash with a key :exitcode and :data. Data is an Array of Hashes where the cooresponding key
89
+ # is either :stdout or :stderr. The reason it is in an Array so so we can get the output in the order it ocurrs on
90
+ # the console.
91
+ def get_command_output(shell_id, command_id, &block)
92
+ s = Savon::SOAP::XML.new
93
+ s.version = 2
94
+ s.namespaces.merge!(namespaces)
95
+ s.header.merge!(merge_headers(header,resource_uri_cmd,action_receive,selector_shell_id(shell_id)))
96
+ s.input = "#{NS_WIN_SHELL}:Receive"
97
+ s.body = { "#{NS_WIN_SHELL}:DesiredStream" => 'stdout stderr',
98
+ :attributes! => {"#{NS_WIN_SHELL}:DesiredStream" => {'CommandId' => command_id}}}
99
+
100
+ resp = send_message(s.to_xml)
101
+ output = {:data => []}
102
+ (resp/"//#{NS_WIN_SHELL}:Stream").each do |n|
103
+ next if n.text.nil? || n.text.empty?
104
+ stream = {n['Name'].to_sym => Base64.decode64(n.text)}
105
+ output[:data] << stream
106
+ yield stream[:stdout], stream[:stderr] if block_given?
107
+ end
108
+
109
+ # We may need to get additional output if the stream has not finished.
110
+ # The CommandState will change from Running to Done like so:
111
+ # @example
112
+ # from...
113
+ # <rsp:CommandState CommandId="..." State="http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandState/Running"/>
114
+ # to...
115
+ # <rsp:CommandState CommandId="..." State="http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandState/Done">
116
+ # <rsp:ExitCode>0</rsp:ExitCode>
117
+ # </rsp:CommandState>
118
+ if((resp/"//#{NS_WIN_SHELL}:ExitCode").empty?)
119
+ output.merge!(get_command_output(shell_id,command_id,&block)) do |key, old_data, new_data|
120
+ old_data += new_data
121
+ end
122
+ else
123
+ output[:exitcode] = (resp/"//#{NS_WIN_SHELL}:ExitCode").text.to_i
124
+ end
125
+ output
126
+ end
127
+
128
+ # Clean-up after a command.
129
+ # @see #run_command
130
+ # @param [String] shell_id The shell id on the remote machine. See #open_shell
131
+ # @param [String] command_id The command id on the remote machine. See #run_command
132
+ # @return [true] This should have more error checking but it just returns true for now.
133
+ def cleanup_command(shell_id, command_id)
134
+ s = Savon::SOAP::XML.new
135
+ s.version = 2
136
+ s.namespaces.merge!(namespaces)
137
+ s.header.merge!(merge_headers(header,resource_uri_cmd,action_signal,selector_shell_id(shell_id)))
138
+
139
+ # Signal the Command references to terminate (close stdout/stderr)
140
+ s.input = ["#{NS_WIN_SHELL}:Signal", {'CommandId' => command_id}]
141
+
142
+ s.body = { "#{NS_WIN_SHELL}:Code" => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/signal/terminate' }
143
+ resp = send_message(s.to_xml)
144
+ true
145
+ end
146
+
147
+ # Close the shell
148
+ # @param [String] shell_id The shell id on the remote machine. See #open_shell
149
+ # @return [true] This should have more error checking but it just returns true for now.
150
+ def close_shell(shell_id)
151
+ s = Savon::SOAP::XML.new
152
+ s.version = 2
153
+ s.namespaces.merge!(namespaces)
154
+ s.namespaces.merge!(Savon::SOAP::XML::SchemaTypes)
155
+ s.header.merge!(merge_headers(header,resource_uri_cmd,action_delete,selector_shell_id(shell_id)))
156
+
157
+ # Because Savon does not support a nil Body we have to build it ourselves.
158
+ s.xml do |b|
159
+ b.tag!('env:Envelope', s.namespaces) do
160
+ b.tag!('env:Header') do |bh|
161
+ bh << Gyoku.xml(s.header) unless s.header.empty?
162
+ end
163
+ if(s.input.nil?)
164
+ b.tag! 'env:Body'
165
+ else
166
+ b.tag! 'env:Body' do |bb|
167
+ bb.tag! s.input do |bbb|
168
+ bbb << Gyoku.xml(s.body) if s.body
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+
175
+ resp = send_message(s.to_xml)
176
+
177
+ resp.remove_namespaces!
178
+ (resp/"//Fault").empty?
179
+ end
180
+
181
+ # Run a CMD command
182
+ # @param [String] command The command to run on the remote system
183
+ # @return [Hash] :stdout and :stderr
184
+ def run_cmd(command, &block)
185
+ shell_id = open_shell
186
+ command_id = run_command(shell_id, command)
187
+ command_output = get_command_output(shell_id, command_id, &block)
188
+ cleanup_command(shell_id, command_id)
189
+ close_shell(shell_id)
190
+ command_output
191
+ end
192
+ alias :cmd :run_cmd
193
+
194
+
195
+ # Run a Powershell script that resides on the local box.
196
+ # @param [IO,String] script_file an IO reference for reading the Powershell script or the actual file contents
197
+ # @return [Hash] :stdout and :stderr
198
+ def run_powershell_script(script_file, &block)
199
+ # if an IO object is passed read it..otherwise assume the contents of the file were passed
200
+ script = script_file.kind_of?(IO) ? script_file.read : script_file
201
+
202
+ script = script.chars.to_a.join("\x00").chomp
203
+ if(defined?(script.encode))
204
+ script = script.encode('ASCII-8BIT')
205
+ script = Base64.strict_encode64(script)
206
+ else
207
+ script = Base64.encode64(script).chomp
208
+ end
209
+
210
+ shell_id = open_shell
211
+ command_id = run_command(shell_id, "powershell -encodedCommand #{script}")
212
+ command_output = get_command_output(shell_id, command_id, &block)
213
+ cleanup_command(shell_id, command_id)
214
+ close_shell(shell_id)
215
+ command_output
216
+ end
217
+
218
+
219
+ # Run a WQL Query
220
+ # @see http://msdn.microsoft.com/en-us/library/aa394606(VS.85).aspx
221
+ # @param [String] wql The WQL query
222
+ # @return [Array<Hash>] Returns an array of Hashes that contain the key/value pairs returned from the query.
223
+ def run_wql(wql)
224
+ header = {}.merge(resource_uri_wmi).merge(action_enumerate)
225
+
226
+ begin
227
+ resp = invoke("#{NS_ENUM}:Enumerate", {:soap_action => :auto, :http_options => nil, :soap_header => header}) do |enum|
228
+ enum.add("#{NS_WSMAN_DMTF}:OptimizeEnumeration")
229
+ enum.add("#{NS_WSMAN_DMTF}:MaxElements",'32000')
230
+ mattr = nil
231
+ enum.add("#{NS_WSMAN_DMTF}:Filter", wql) do |filt|
232
+ filt.set_attr('Dialect','http://schemas.microsoft.com/wbem/wsman/1/WQL')
233
+ end
234
+ end
235
+ rescue Handsoap::Fault => e
236
+ raise WinRMWebServiceError, e.reason
237
+ end
238
+
239
+ query_response = []
240
+ (resp/"//#{NS_ENUM}:EnumerateResponse//#{NS_WSMAN_DMTF}:Items/*").each do |i|
241
+ qitem = {}
242
+ (i/'*').each do |si|
243
+ qitem[si.node_name] = si.to_s
244
+ end
245
+ query_response << qitem
246
+ end
247
+ query_response
248
+ end
249
+
250
+
251
+
252
+ private
253
+
254
+ def namespaces
255
+ {'xmlns:a' => 'http://schemas.xmlsoap.org/ws/2004/08/addressing',
256
+ 'xmlns:b' => 'http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd',
257
+ 'xmlns:n' => 'http://schemas.xmlsoap.org/ws/2004/09/enumeration',
258
+ 'xmlns:x' => 'http://schemas.xmlsoap.org/ws/2004/09/transfer',
259
+ 'xmlns:w' => 'http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd',
260
+ 'xmlns:p' => 'http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd',
261
+ 'xmlns:rsp' => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell'}
262
+ end
263
+
264
+ def header
265
+ { "#{NS_ADDRESSING}:To" => "#{@xfer.endpoint.to_s}",
266
+ "#{NS_ADDRESSING}:ReplyTo" => {
267
+ "#{NS_ADDRESSING}:Address" => 'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous',
268
+ :attributes! => {"#{NS_ADDRESSING}:Address" => {'mustUnderstand' => true}}},
269
+ "#{NS_WSMAN_DMTF}:MaxEnvelopeSize" => @max_env_sz,
270
+ "#{NS_ADDRESSING}:MessageID" => "uuid:#{UUID.generate.upcase}",
271
+ "#{NS_WSMAN_DMTF}:Locale/" => '',
272
+ "#{NS_WSMAN_MSFT}:DataLocale/" => '',
273
+ "#{NS_WSMAN_DMTF}:OperationTimeout" => @timeout,
274
+ :attributes! => {
275
+ "#{NS_WSMAN_DMTF}:MaxEnvelopeSize" => {'mustUnderstand' => true},
276
+ "#{NS_WSMAN_DMTF}:Locale/" => {'xml:lang' => @locale, 'mustUnderstand' => false},
277
+ "#{NS_WSMAN_MSFT}:DataLocale/" => {'xml:lang' => @locale, 'mustUnderstand' => false}
278
+ }}
279
+ end
280
+
281
+ # merge the various header hashes and make sure we carry all of the attributes
282
+ # through instead of overwriting them.
283
+ def merge_headers(*headers)
284
+ hdr = {}
285
+ headers.each do |h|
286
+ hdr.merge!(h) do |k,v1,v2|
287
+ v1.merge!(v2) if k == :attributes!
288
+ end
289
+ end
290
+ hdr
291
+ end
292
+
293
+ def send_message(message)
294
+ resp = @xfer.send_request(message)
295
+
296
+ errors = resp/"//#{NS_SOAP_ENV}:Body/#{NS_SOAP_ENV}:Fault/*"
297
+ if errors.empty?
298
+ return resp
299
+ else
300
+ resp.root.add_namespace(NS_WSMAN_FAULT,'http://schemas.microsoft.com/wbem/wsman/1/wsmanfault')
301
+ fault = (errors/"//#{NS_WSMAN_FAULT}:WSManFault").first
302
+ raise WinRMWSManFault, "[WSMAN ERROR CODE: #{fault['Code']}]: #{fault.text}"
303
+ end
304
+ end
305
+
306
+ # Helper methods for SOAP Headers
307
+
308
+ def resource_uri_cmd
309
+ {"#{NS_WSMAN_DMTF}:ResourceURI" => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd',
310
+ :attributes! => {"#{NS_WSMAN_DMTF}:ResourceURI" => {'mustUnderstand' => true}}}
311
+ end
312
+
313
+ def resource_uri_wmi(namespace = 'root/cimv2/*')
314
+ {"#{NS_WSMAN_DMTF}:ResourceURI" => "http://schemas.microsoft.com/wbem/wsman/1/wmi/#{namespace}",
315
+ :attributes! => {"#{NS_WSMAN_DMTF}:ResourceURI" => {'mustUnderstand' => true}}}
316
+ end
317
+
318
+ def action_create
319
+ {"#{NS_ADDRESSING}:Action" => 'http://schemas.xmlsoap.org/ws/2004/09/transfer/Create',
320
+ :attributes! => {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => true}}}
321
+ end
322
+
323
+ def action_delete
324
+ {"#{NS_ADDRESSING}:Action" => 'http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete',
325
+ :attributes! => {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => true}}}
326
+ end
327
+
328
+ def action_command
329
+ {"#{NS_ADDRESSING}:Action" => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Command',
330
+ :attributes! => {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => true}}}
331
+ end
332
+
333
+ def action_receive
334
+ {"#{NS_ADDRESSING}:Action" => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Receive',
335
+ :attributes! => {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => true}}}
336
+ end
337
+
338
+ def action_signal
339
+ {"#{NS_ADDRESSING}:Action" => 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Signal',
340
+ :attributes! => {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => true}}}
341
+ end
342
+
343
+ def action_enumerate
344
+ {"#{NS_ADDRESSING}:Action" => 'http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate',
345
+ :attributes! => {"#{NS_ADDRESSING}:Action" => {'mustUnderstand' => true}}}
346
+ end
347
+
348
+ def selector_shell_id(shell_id)
349
+ {"#{NS_WSMAN_DMTF}:SelectorSet" =>
350
+ {"#{NS_WSMAN_DMTF}:Selector" => shell_id, :attributes! => {"#{NS_WSMAN_DMTF}:Selector" => {'Name' => 'ShellId'}}}
351
+ }
352
+ end
353
+
354
+ end # WinRMWebService
355
+ end # WinRM
356
+
data/winrm.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'date'
3
+
4
+ version = File.read(File.expand_path("../VERSION", __FILE__)).strip
5
+
6
+ Gem::Specification.new do |s|
7
+ s.platform = Gem::Platform::RUBY
8
+ s.name = 'winrm'
9
+ s.version = version
10
+ s.date = Date.today.to_s
11
+
12
+ s.author = 'Dan Wanek'
13
+ s.email = 'dan.wanek@gmail.com'
14
+ s.homepage = "http://github.com/zenchild/WinRM"
15
+
16
+ s.summary = 'Ruby library for Windows Remote Management'
17
+ s.description = <<-EOF
18
+ Ruby library for Windows Remote Management
19
+ EOF
20
+
21
+ s.files = `git ls-files`.split(/\n/)
22
+ s.require_path = "lib"
23
+ s.rdoc_options = %w(-x test/ -x examples/)
24
+ s.extra_rdoc_files = %w(README COPYING.txt)
25
+
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 'uuid'
32
+ s.add_runtime_dependency 'savon'
33
+ end
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: winrm
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 6
9
- version: 0.0.6
4
+ prerelease: 5
5
+ version: 1.0.0rc1
10
6
  platform: ruby
11
7
  authors:
12
8
  - Dan Wanek
@@ -14,19 +10,17 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2010-10-22 00:00:00 -05:00
13
+ date: 2011-02-28 00:00:00 -06:00
18
14
  default_executable:
19
15
  dependencies:
20
16
  - !ruby/object:Gem::Dependency
21
- name: handsoap
17
+ name: gssapi
22
18
  prerelease: false
23
19
  requirement: &id001 !ruby/object:Gem::Requirement
24
20
  none: false
25
21
  requirements:
26
22
  - - ">="
27
23
  - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
24
  version: "0"
31
25
  type: :runtime
32
26
  version_requirements: *id001
@@ -38,8 +32,6 @@ dependencies:
38
32
  requirements:
39
33
  - - ">="
40
34
  - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
35
  version: "0"
44
36
  type: :runtime
45
37
  version_requirements: *id002
@@ -51,8 +43,6 @@ dependencies:
51
43
  requirements:
52
44
  - - ">="
53
45
  - !ruby/object:Gem::Version
54
- segments:
55
- - 0
56
46
  version: "0"
57
47
  type: :runtime
58
48
  version_requirements: *id003
@@ -64,8 +54,6 @@ dependencies:
64
54
  requirements:
65
55
  - - ">="
66
56
  - !ruby/object:Gem::Version
67
- segments:
68
- - 0
69
57
  version: "0"
70
58
  type: :runtime
71
59
  version_requirements: *id004
@@ -77,11 +65,20 @@ dependencies:
77
65
  requirements:
78
66
  - - ">="
79
67
  - !ruby/object:Gem::Version
80
- segments:
81
- - 0
82
68
  version: "0"
83
69
  type: :runtime
84
70
  version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: savon
73
+ prerelease: false
74
+ requirement: &id006 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ type: :runtime
81
+ version_requirements: *id006
85
82
  description: " Ruby library for Windows Remote Management\n"
86
83
  email: dan.wanek@gmail.com
87
84
  executables: []
@@ -96,16 +93,18 @@ files:
96
93
  - README
97
94
  - Rakefile
98
95
  - VERSION
99
- - lib/extensions/string.rb
100
- - lib/soap/exceptions/exceptions.rb
101
- - lib/soap/soap_provider.rb
102
- - lib/soap/winrm_service.rb
103
96
  - lib/winrm.rb
97
+ - lib/winrm/exceptions/exceptions.rb
98
+ - lib/winrm/helpers/iso8601_duration.rb
99
+ - lib/winrm/http/transport.rb
100
+ - lib/winrm/soap_provider.rb
101
+ - lib/winrm/winrm_service.rb
104
102
  - preamble
105
103
  - test/spec/powershell_tests.spec
106
104
  - test/spec/spec.opts
107
105
  - test/spec/test.ps1
108
106
  - test/spec/wql_tests.spec
107
+ - winrm.gemspec
109
108
  has_rdoc: true
110
109
  homepage: http://github.com/zenchild/WinRM
111
110
  licenses: []
@@ -123,23 +122,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
123
122
  requirements:
124
123
  - - ">="
125
124
  - !ruby/object:Gem::Version
126
- segments:
127
- - 1
128
- - 8
129
- - 7
130
- version: 1.8.7
125
+ version: 1.9.0
131
126
  required_rubygems_version: !ruby/object:Gem::Requirement
132
127
  none: false
133
128
  requirements:
134
- - - ">="
129
+ - - ">"
135
130
  - !ruby/object:Gem::Version
136
- segments:
137
- - 0
138
- version: "0"
131
+ version: 1.3.1
139
132
  requirements: []
140
133
 
141
134
  rubyforge_project:
142
- rubygems_version: 1.3.7
135
+ rubygems_version: 1.5.0
143
136
  signing_key:
144
137
  specification_version: 3
145
138
  summary: Ruby library for Windows Remote Management