winrm 1.7.1 → 1.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +10 -10
  3. data/.rspec +3 -3
  4. data/.rubocop.yml +12 -12
  5. data/.travis.yml +12 -12
  6. data/Gemfile +9 -9
  7. data/LICENSE +202 -202
  8. data/README.md +194 -194
  9. data/Rakefile +36 -36
  10. data/Vagrantfile +9 -9
  11. data/appveyor.yml +42 -42
  12. data/bin/rwinrm +97 -97
  13. data/changelog.md +77 -74
  14. data/lib/winrm.rb +42 -42
  15. data/lib/winrm/command_executor.rb +224 -224
  16. data/lib/winrm/command_output_decoder.rb +53 -0
  17. data/lib/winrm/exceptions/exceptions.rb +57 -57
  18. data/lib/winrm/helpers/iso8601_duration.rb +58 -58
  19. data/lib/winrm/helpers/powershell_script.rb +42 -42
  20. data/lib/winrm/http/response_handler.rb +82 -82
  21. data/lib/winrm/http/transport.rb +421 -421
  22. data/lib/winrm/output.rb +43 -43
  23. data/lib/winrm/soap_provider.rb +39 -39
  24. data/lib/winrm/version.rb +7 -7
  25. data/lib/winrm/winrm_service.rb +547 -556
  26. data/preamble +17 -17
  27. data/spec/auth_timeout_spec.rb +16 -16
  28. data/spec/cmd_spec.rb +102 -102
  29. data/spec/command_executor_spec.rb +429 -429
  30. data/spec/command_output_decoder_spec.rb +37 -0
  31. data/spec/config-example.yml +19 -19
  32. data/spec/exception_spec.rb +50 -50
  33. data/spec/issue_184_spec.rb +67 -67
  34. data/spec/issue_59_spec.rb +23 -23
  35. data/spec/matchers.rb +74 -74
  36. data/spec/output_spec.rb +110 -110
  37. data/spec/powershell_spec.rb +97 -97
  38. data/spec/response_handler_spec.rb +59 -59
  39. data/spec/spec_helper.rb +73 -73
  40. data/spec/stubs/responses/get_command_output_response.xml.erb +13 -13
  41. data/spec/stubs/responses/open_shell_v1.xml +19 -19
  42. data/spec/stubs/responses/open_shell_v2.xml +20 -20
  43. data/spec/stubs/responses/soap_fault_v1.xml +36 -36
  44. data/spec/stubs/responses/soap_fault_v2.xml +42 -42
  45. data/spec/stubs/responses/wmi_error_v2.xml +41 -41
  46. data/spec/transport_spec.rb +124 -124
  47. data/spec/winrm_options_spec.rb +76 -76
  48. data/spec/winrm_primitives_spec.rb +51 -51
  49. data/spec/wql_spec.rb +14 -14
  50. data/winrm.gemspec +40 -40
  51. metadata +5 -3
@@ -0,0 +1,37 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'winrm/command_output_decoder'
4
+
5
+ describe WinRM::CommandOutputDecoder, unit: true do
6
+ let(:raw_output_with_bom) do
7
+ '77u/' \
8
+ 'ICAgQ29ubmVjdGlvbi1zcGVjaWZpYyBETlMgU3VmZml4ICAuIDogDQogICBMaW5rLWxvY2FsIElQdjYgQWRkcmVzcyA' \
9
+ 'uIC4gLiAuIC4gOiBmZTgwOjo5MTFkOjE2OTQ6NTcwNDo1YjI5JTEyDQogICBJUHY0IEFkZHJlc3MuIC4gLiAuIC4gLi' \
10
+ 'AuIC4gLiAuIC4gOiAxMC4wLjIuMTUNCiAgIFN1Ym5ldCBNYXNrIC4gLiAuIC4gLiAuIC4gLiAuIC4gLiA6IDI1NS4yN' \
11
+ 'TUuMjU1LjANCiAgIERlZmF1bHQgR2F0ZXdheSAuIC4gLiAuIC4gLiAuIC4gLiA6IDEwLjAuMi4yDQoNClR1bm5lbCBh' \
12
+ 'ZGFwdGVyIGlzYXRhcC57RjBENTY2RDgtNzlCMS00QUYwLUJENUQtMkM5RkVEOEI3MTE3fToNCg0KICAgTWVkaWEgU3R' \
13
+ 'hdGUgLiAuIC4gLiAuIC4gLiAuIC4gLiAuIDogTWVkaWEgZGlzY29ubmVjdGVkDQogICBDb25uZWN0aW9uLXNwZWNpZm' \
14
+ 'ljIEROUyBTdWZmaXggIC4gOiANCg0KVHVubmVsIGFkYXB0ZXIgVGVyZWRvIFR1bm5lbGluZyBQc2V1ZG8tSW50ZXJmY' \
15
+ 'WNlOg0KDQogICBDb25uZWN0aW9uLXNwZWNpZmljIEROUyBTdWZmaXggIC4gOiANCiAgIElQdjYgQWRkcmVzcy4gLiAu' \
16
+ 'IC4gLiAuIC4gLiAuIC4gLiA6IDIwMDE6MDo5ZDM4OjZhYmQ6NGJiOjI4YjU6ZjVmZjpmZGYwDQogICBMaW5rLWxvY2F' \
17
+ 'sIElQdjYgQWRkcmVzcyAuIC4gLiAuIC4gOiBmZTgwOjo0YmI6MjhiNTpmNWZmOmZkZjAlMTQNCiAgIERlZmF1bHQgR2' \
18
+ 'F0ZXdheSAuIC4gLiAuIC4gLiAuIC4gLiA6IDo6DQo='
19
+ end
20
+ let(:expected) do
21
+ " Connection-specific DNS Suffix . : \r\n Link-local IPv6 Address . . . . . : fe80::911" \
22
+ "d:1694:5704:5b29%12\r\n IPv4 Address. . . . . . . . . . . : 10.0.2.15\r\n Subnet Mask ." \
23
+ " . . . . . . . . . . : 255.255.255.0\r\n Default Gateway . . . . . . . . . : 10.0.2.2\r\n" \
24
+ "\r\nTunnel adapter isatap.{F0D566D8-79B1-4AF0-BD5D-2C9FED8B7117}:\r\n\r\n Media State . ." \
25
+ " . . . . . . . . . : Media disconnected\r\n Connection-specific DNS Suffix . : \r\n\r\nT" \
26
+ "unnel adapter Teredo Tunneling Pseudo-Interface:\r\n\r\n Connection-specific DNS Suffix " \
27
+ ". : \r\n IPv6 Address. . . . . . . . . . . : 2001:0:9d38:6abd:4bb:28b5:f5ff:fdf0\r\n Li" \
28
+ "nk-local IPv6 Address . . . . . : fe80::4bb:28b5:f5ff:fdf0%14\r\n Default Gateway . . . ." \
29
+ " . . . . . : ::\r\n"
30
+ end
31
+ subject { described_class.new }
32
+ context 'valid UTF-8 raw output' do
33
+ it 'decodes' do
34
+ expect(subject.decode(raw_output_with_bom)).to eq(expected)
35
+ end
36
+ end
37
+ end
@@ -1,19 +1,19 @@
1
- # Copy this file to config.yml and edit the settings below.
2
- # This should work out of the box for vagrant provisioned boxes.
3
-
4
- ## Kerberos
5
- #auth_type: kerberos
6
- #endpoint: "http://<yourserver>:5985/wsman"
7
- #options:
8
- # realm: "your.realm"
9
-
10
- ## Plain Text
11
- auth_type: plaintext
12
- # If you are running this in a vagrant provisioned box using NAT,
13
- # this will be the forwarded WinRM HTTP port to your VM.
14
- # If you are running this on the VM, the default HTTP port is 5985.
15
- # See README.md#Troubleshooting.
16
- endpoint: "http://localhost:55985/wsman"
17
- options:
18
- user: vagrant
19
- pass: vagrant
1
+ # Copy this file to config.yml and edit the settings below.
2
+ # This should work out of the box for vagrant provisioned boxes.
3
+
4
+ ## Kerberos
5
+ #auth_type: kerberos
6
+ #endpoint: "http://<yourserver>:5985/wsman"
7
+ #options:
8
+ # realm: "your.realm"
9
+
10
+ ## Plain Text
11
+ auth_type: plaintext
12
+ # If you are running this in a vagrant provisioned box using NAT,
13
+ # this will be the forwarded WinRM HTTP port to your VM.
14
+ # If you are running this on the VM, the default HTTP port is 5985.
15
+ # See README.md#Troubleshooting.
16
+ endpoint: "http://localhost:55985/wsman"
17
+ options:
18
+ user: vagrant
19
+ pass: vagrant
@@ -1,50 +1,50 @@
1
- # encoding: UTF-8
2
- describe 'Exceptions', unit: true do
3
- describe WinRM::WinRMAuthorizationError do
4
- let(:error) { WinRM::WinRMHTTPTransportError.new('Foo happened', 500) }
5
-
6
- it 'adds the response code to the message' do
7
- expect(error.message).to eq('Foo happened (500).')
8
- end
9
-
10
- it 'exposes the response code as an attribute' do
11
- expect(error.status_code).to eq 500
12
- end
13
-
14
- it 'is a winrm error' do
15
- expect(error).to be_kind_of(WinRM::WinRMError)
16
- end
17
- end
18
-
19
- describe WinRM::WinRMWSManFault do
20
- let(:error) { WinRM::WinRMWSManFault.new('fault text', 42) }
21
-
22
- it 'exposes the fault text as an attribute' do
23
- expect(error.fault_description).to eq('fault text')
24
- end
25
-
26
- it 'exposes the fault code as an attribute' do
27
- expect(error.fault_code).to eq 42
28
- end
29
-
30
- it 'is a winrm error' do
31
- expect(error).to be_kind_of(WinRM::WinRMError)
32
- end
33
- end
34
-
35
- describe WinRM::WinRMWMIError do
36
- let(:error) { WinRM::WinRMWMIError.new('message text', 77_777) }
37
-
38
- it 'exposes the error text as an attribute' do
39
- expect(error.error).to eq('message text')
40
- end
41
-
42
- it 'exposes the error code as an attribute' do
43
- expect(error.error_code).to eq 77_777
44
- end
45
-
46
- it 'is a winrm error' do
47
- expect(error).to be_kind_of(WinRM::WinRMError)
48
- end
49
- end
50
- end
1
+ # encoding: UTF-8
2
+ describe 'Exceptions', unit: true do
3
+ describe WinRM::WinRMAuthorizationError do
4
+ let(:error) { WinRM::WinRMHTTPTransportError.new('Foo happened', 500) }
5
+
6
+ it 'adds the response code to the message' do
7
+ expect(error.message).to eq('Foo happened (500).')
8
+ end
9
+
10
+ it 'exposes the response code as an attribute' do
11
+ expect(error.status_code).to eq 500
12
+ end
13
+
14
+ it 'is a winrm error' do
15
+ expect(error).to be_kind_of(WinRM::WinRMError)
16
+ end
17
+ end
18
+
19
+ describe WinRM::WinRMWSManFault do
20
+ let(:error) { WinRM::WinRMWSManFault.new('fault text', 42) }
21
+
22
+ it 'exposes the fault text as an attribute' do
23
+ expect(error.fault_description).to eq('fault text')
24
+ end
25
+
26
+ it 'exposes the fault code as an attribute' do
27
+ expect(error.fault_code).to eq 42
28
+ end
29
+
30
+ it 'is a winrm error' do
31
+ expect(error).to be_kind_of(WinRM::WinRMError)
32
+ end
33
+ end
34
+
35
+ describe WinRM::WinRMWMIError do
36
+ let(:error) { WinRM::WinRMWMIError.new('message text', 77_777) }
37
+
38
+ it 'exposes the error text as an attribute' do
39
+ expect(error.error).to eq('message text')
40
+ end
41
+
42
+ it 'exposes the error code as an attribute' do
43
+ expect(error.error_code).to eq 77_777
44
+ end
45
+
46
+ it 'is a winrm error' do
47
+ expect(error).to be_kind_of(WinRM::WinRMError)
48
+ end
49
+ end
50
+ end
@@ -1,67 +1,67 @@
1
- # encoding: UTF-8
2
- require 'winrm/winrm_service'
3
- require 'rexml/document'
4
- require 'erb'
5
- require 'base64'
6
-
7
- describe 'issue 184', unit: true do
8
- let(:shell_id) { 'shell-123' }
9
- let(:command_id) { 123 }
10
- let(:test_data_xml_template) do
11
- ERB.new(File.read('spec/stubs/responses/get_command_output_response.xml.erb'))
12
- end
13
- let(:service) do
14
- WinRM::WinRMWebService.new(
15
- 'http://dummy/wsman',
16
- :plaintext,
17
- user: 'dummy',
18
- pass: 'dummy')
19
- end
20
-
21
- describe 'response doc stdout with invalid UTF-8 characters' do
22
- let(:test_data_stdout) { 'ffff' } # Base64-decodes to '}\xF7\xDF', an invalid sequence
23
- let(:test_data_stderr) { '' }
24
- let(:test_data_xml) { test_data_xml_template.result(binding) }
25
-
26
- before do
27
- allow(service).to receive(:send_get_output_message).and_return(
28
- REXML::Document.new(test_data_xml)
29
- )
30
- end
31
-
32
- it 'does not raise an ArgumentError: invalid byte sequence in UTF-8' do
33
- begin
34
- expect(
35
- service.get_command_output(shell_id, command_id)
36
- ).not_to raise_error
37
- rescue RSpec::Expectations::ExpectationNotMetError => e
38
- expect(e.message).not_to include 'ArgumentError'
39
- end
40
- end
41
-
42
- it 'does not have an empty stdout' do
43
- expect(
44
- service.get_command_output(shell_id, command_id)[:data][0][:stdout]
45
- ).not_to be_empty
46
- end
47
- end
48
-
49
- describe 'response doc stdout with valid UTF-8' do
50
- let(:test_data_raw) { '✓1234-äöü' }
51
- let(:test_data_stdout) { Base64.encode64(test_data_raw) }
52
- let(:test_data_stderr) { '' }
53
- let(:test_data_xml) { test_data_xml_template.result(binding) }
54
-
55
- before do
56
- allow(service).to receive(:send_get_output_message).and_return(
57
- REXML::Document.new(test_data_xml)
58
- )
59
- end
60
-
61
- it 'decodes to match input data' do
62
- expect(
63
- service.get_command_output(shell_id, command_id)[:data][0][:stdout]
64
- ).to eq(test_data_raw)
65
- end
66
- end
67
- end
1
+ # encoding: UTF-8
2
+ require 'winrm/winrm_service'
3
+ require 'rexml/document'
4
+ require 'erb'
5
+ require 'base64'
6
+
7
+ describe 'issue 184', unit: true do
8
+ let(:shell_id) { 'shell-123' }
9
+ let(:command_id) { 123 }
10
+ let(:test_data_xml_template) do
11
+ ERB.new(File.read('spec/stubs/responses/get_command_output_response.xml.erb'))
12
+ end
13
+ let(:service) do
14
+ WinRM::WinRMWebService.new(
15
+ 'http://dummy/wsman',
16
+ :plaintext,
17
+ user: 'dummy',
18
+ pass: 'dummy')
19
+ end
20
+
21
+ describe 'response doc stdout with invalid UTF-8 characters' do
22
+ let(:test_data_stdout) { 'ffff' } # Base64-decodes to '}\xF7\xDF', an invalid sequence
23
+ let(:test_data_stderr) { '' }
24
+ let(:test_data_xml) { test_data_xml_template.result(binding) }
25
+
26
+ before do
27
+ allow(service).to receive(:send_get_output_message).and_return(
28
+ REXML::Document.new(test_data_xml)
29
+ )
30
+ end
31
+
32
+ it 'does not raise an ArgumentError: invalid byte sequence in UTF-8' do
33
+ begin
34
+ expect(
35
+ service.get_command_output(shell_id, command_id)
36
+ ).not_to raise_error
37
+ rescue RSpec::Expectations::ExpectationNotMetError => e
38
+ expect(e.message).not_to include 'ArgumentError'
39
+ end
40
+ end
41
+
42
+ it 'does not have an empty stdout' do
43
+ expect(
44
+ service.get_command_output(shell_id, command_id)[:data][0][:stdout]
45
+ ).not_to be_empty
46
+ end
47
+ end
48
+
49
+ describe 'response doc stdout with valid UTF-8' do
50
+ let(:test_data_raw) { '✓1234-äöü' }
51
+ let(:test_data_stdout) { Base64.encode64(test_data_raw) }
52
+ let(:test_data_stderr) { '' }
53
+ let(:test_data_xml) { test_data_xml_template.result(binding) }
54
+
55
+ before do
56
+ allow(service).to receive(:send_get_output_message).and_return(
57
+ REXML::Document.new(test_data_xml)
58
+ )
59
+ end
60
+
61
+ it 'decodes to match input data' do
62
+ expect(
63
+ service.get_command_output(shell_id, command_id)[:data][0][:stdout]
64
+ ).to eq(test_data_raw)
65
+ end
66
+ end
67
+ end
@@ -1,23 +1,23 @@
1
- # encoding: UTF-8
2
- describe 'issue 59', integration: true do
3
- before(:all) do
4
- @winrm = winrm_connection
5
- end
6
-
7
- describe 'long running script without output' do
8
- let(:logged_output) { StringIO.new }
9
- let(:logger) { Logging.logger(logged_output) }
10
-
11
- it 'should not error' do
12
- @winrm.set_timeout(1)
13
- @winrm.logger = logger
14
-
15
- out = @winrm.powershell('$ProgressPreference="SilentlyContinue";sleep 3; Write-Host "Hello"')
16
-
17
- expect(out).to have_exit_code 0
18
- expect(out).to have_stdout_match(/Hello/)
19
- expect(out).to have_no_stderr
20
- expect(logged_output.string).to match(/retrying receive request/)
21
- end
22
- end
23
- end
1
+ # encoding: UTF-8
2
+ describe 'issue 59', integration: true do
3
+ before(:all) do
4
+ @winrm = winrm_connection
5
+ end
6
+
7
+ describe 'long running script without output' do
8
+ let(:logged_output) { StringIO.new }
9
+ let(:logger) { Logging.logger(logged_output) }
10
+
11
+ it 'should not error' do
12
+ @winrm.set_timeout(1)
13
+ @winrm.logger = logger
14
+
15
+ out = @winrm.powershell('$ProgressPreference="SilentlyContinue";sleep 3; Write-Host "Hello"')
16
+
17
+ expect(out).to have_exit_code 0
18
+ expect(out).to have_stdout_match(/Hello/)
19
+ expect(out).to have_no_stderr
20
+ expect(logged_output.string).to match(/retrying receive request/)
21
+ end
22
+ end
23
+ end
data/spec/matchers.rb CHANGED
@@ -1,74 +1,74 @@
1
- # encoding: UTF-8
2
- require 'rspec/expectations'
3
-
4
- # rspec matchers
5
- module WinRMSpecs
6
- def self.stdout(output)
7
- output[:data].collect do |i|
8
- i[:stdout]
9
- end.join('\r\n').gsub(/(\\r\\n)+$/, '')
10
- end
11
-
12
- def self.stderr(output)
13
- output[:data].collect do |i|
14
- i[:stderr]
15
- end.join('\r\n').gsub(/(\\r\\n)+$/, '')
16
- end
17
- end
18
-
19
- RSpec::Matchers.define :have_stdout_match do |expected_stdout|
20
- match do |actual_output|
21
- !expected_stdout.match(WinRMSpecs.stdout(actual_output)).nil?
22
- end
23
- failure_message do |actual_output|
24
- "expected that '#{WinRMSpecs.stdout(actual_output)}' would match #{expected_stdout}"
25
- end
26
- end
27
-
28
- RSpec::Matchers.define :have_stderr_match do |expected_stderr|
29
- match do |actual_output|
30
- !expected_stderr.match(WinRMSpecs.stderr(actual_output)).nil?
31
- end
32
- failure_message do |actual_output|
33
- "expected that '#{WinRMSpecs.stderr(actual_output)}' would match #{expected_stderr}"
34
- end
35
- end
36
-
37
- RSpec::Matchers.define :have_no_stdout do
38
- match do |actual_output|
39
- stdout = WinRMSpecs.stdout(actual_output)
40
- stdout == '\r\n' || stdout == ''
41
- end
42
- failure_message do |actual_output|
43
- "expected that '#{WinRMSpecs.stdout(actual_output)}' would have no stdout"
44
- end
45
- end
46
-
47
- RSpec::Matchers.define :have_no_stderr do
48
- match do |actual_output|
49
- stderr = WinRMSpecs.stderr(actual_output)
50
- stderr == '\r\n' || stderr == ''
51
- end
52
- failure_message do |actual_output|
53
- "expected that '#{WinRMSpecs.stderr(actual_output)}' would have no stderr"
54
- end
55
- end
56
-
57
- RSpec::Matchers.define :have_exit_code do |expected_exit_code|
58
- match do |actual_output|
59
- expected_exit_code == actual_output[:exitcode]
60
- end
61
- failure_message do |actual_output|
62
- "expected exit code #{expected_exit_code}, but got #{actual_output[:exitcode]}"
63
- end
64
- end
65
-
66
- RSpec::Matchers.define :be_a_uid do
67
- match do |actual|
68
- # WinRM1.1 returns uuid's prefixed with 'uuid:' where as later versions do not
69
- actual && actual.to_s.match(/^(uuid:)*\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/)
70
- end
71
- failure_message do |actual|
72
- "expected a uid, but got '#{actual}'"
73
- end
74
- end
1
+ # encoding: UTF-8
2
+ require 'rspec/expectations'
3
+
4
+ # rspec matchers
5
+ module WinRMSpecs
6
+ def self.stdout(output)
7
+ output[:data].collect do |i|
8
+ i[:stdout]
9
+ end.join('\r\n').gsub(/(\\r\\n)+$/, '')
10
+ end
11
+
12
+ def self.stderr(output)
13
+ output[:data].collect do |i|
14
+ i[:stderr]
15
+ end.join('\r\n').gsub(/(\\r\\n)+$/, '')
16
+ end
17
+ end
18
+
19
+ RSpec::Matchers.define :have_stdout_match do |expected_stdout|
20
+ match do |actual_output|
21
+ !expected_stdout.match(WinRMSpecs.stdout(actual_output)).nil?
22
+ end
23
+ failure_message do |actual_output|
24
+ "expected that '#{WinRMSpecs.stdout(actual_output)}' would match #{expected_stdout}"
25
+ end
26
+ end
27
+
28
+ RSpec::Matchers.define :have_stderr_match do |expected_stderr|
29
+ match do |actual_output|
30
+ !expected_stderr.match(WinRMSpecs.stderr(actual_output)).nil?
31
+ end
32
+ failure_message do |actual_output|
33
+ "expected that '#{WinRMSpecs.stderr(actual_output)}' would match #{expected_stderr}"
34
+ end
35
+ end
36
+
37
+ RSpec::Matchers.define :have_no_stdout do
38
+ match do |actual_output|
39
+ stdout = WinRMSpecs.stdout(actual_output)
40
+ stdout == '\r\n' || stdout == ''
41
+ end
42
+ failure_message do |actual_output|
43
+ "expected that '#{WinRMSpecs.stdout(actual_output)}' would have no stdout"
44
+ end
45
+ end
46
+
47
+ RSpec::Matchers.define :have_no_stderr do
48
+ match do |actual_output|
49
+ stderr = WinRMSpecs.stderr(actual_output)
50
+ stderr == '\r\n' || stderr == ''
51
+ end
52
+ failure_message do |actual_output|
53
+ "expected that '#{WinRMSpecs.stderr(actual_output)}' would have no stderr"
54
+ end
55
+ end
56
+
57
+ RSpec::Matchers.define :have_exit_code do |expected_exit_code|
58
+ match do |actual_output|
59
+ expected_exit_code == actual_output[:exitcode]
60
+ end
61
+ failure_message do |actual_output|
62
+ "expected exit code #{expected_exit_code}, but got #{actual_output[:exitcode]}"
63
+ end
64
+ end
65
+
66
+ RSpec::Matchers.define :be_a_uid do
67
+ match do |actual|
68
+ # WinRM1.1 returns uuid's prefixed with 'uuid:' where as later versions do not
69
+ actual && actual.to_s.match(/^(uuid:)*\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/)
70
+ end
71
+ failure_message do |actual|
72
+ "expected a uid, but got '#{actual}'"
73
+ end
74
+ end