winrm 2.2.3 → 2.3.6

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.
Files changed (127) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +1 -1
  3. data/bin/rwinrm +90 -97
  4. data/lib/winrm/connection.rb +84 -86
  5. data/lib/winrm/connection_opts.rb +90 -91
  6. data/lib/winrm/exceptions.rb +14 -2
  7. data/lib/winrm/http/response_handler.rb +127 -96
  8. data/lib/winrm/http/transport.rb +462 -427
  9. data/lib/winrm/http/transport_factory.rb +1 -5
  10. data/lib/winrm/output.rb +1 -2
  11. data/lib/winrm/psrp/fragment.rb +0 -2
  12. data/lib/winrm/psrp/message.rb +128 -130
  13. data/lib/winrm/psrp/message_data/base.rb +0 -2
  14. data/lib/winrm/psrp/message_data/error_record.rb +2 -2
  15. data/lib/winrm/psrp/message_data/pipeline_host_call.rb +0 -2
  16. data/lib/winrm/psrp/message_data/pipeline_output.rb +48 -54
  17. data/lib/winrm/psrp/message_data/pipeline_state.rb +0 -2
  18. data/lib/winrm/psrp/message_data/runspacepool_host_call.rb +0 -2
  19. data/lib/winrm/psrp/message_data/runspacepool_state.rb +0 -2
  20. data/lib/winrm/psrp/message_data/session_capability.rb +0 -2
  21. data/lib/winrm/psrp/message_data.rb +0 -2
  22. data/lib/winrm/psrp/message_defragmenter.rb +2 -2
  23. data/lib/winrm/psrp/message_factory.rb +16 -5
  24. data/lib/winrm/psrp/message_fragmenter.rb +1 -3
  25. data/lib/winrm/psrp/powershell_output_decoder.rb +142 -144
  26. data/lib/winrm/psrp/receive_response_reader.rb +3 -5
  27. data/lib/winrm/psrp/uuid.rb +1 -2
  28. data/lib/winrm/shells/base.rb +7 -4
  29. data/lib/winrm/shells/cmd.rb +63 -65
  30. data/lib/winrm/shells/power_shell.rb +207 -202
  31. data/lib/winrm/shells/retryable.rb +44 -45
  32. data/lib/winrm/shells/shell_factory.rb +0 -2
  33. data/lib/winrm/version.rb +1 -3
  34. data/lib/winrm/wsmv/base.rb +0 -2
  35. data/lib/winrm/wsmv/cleanup_command.rb +1 -2
  36. data/lib/winrm/wsmv/close_shell.rb +1 -2
  37. data/lib/winrm/wsmv/command.rb +2 -3
  38. data/lib/winrm/wsmv/command_output.rb +2 -3
  39. data/lib/winrm/wsmv/command_output_decoder.rb +1 -2
  40. data/lib/winrm/wsmv/configuration.rb +0 -2
  41. data/lib/winrm/wsmv/create_pipeline.rb +0 -2
  42. data/lib/winrm/wsmv/create_shell.rb +2 -6
  43. data/lib/winrm/wsmv/header.rb +213 -215
  44. data/lib/winrm/wsmv/init_runspace_pool.rb +96 -95
  45. data/lib/winrm/wsmv/iso8601_duration.rb +0 -2
  46. data/lib/winrm/wsmv/keep_alive.rb +0 -2
  47. data/lib/winrm/wsmv/receive_response_reader.rb +128 -126
  48. data/lib/winrm/wsmv/send_data.rb +0 -2
  49. data/lib/winrm/wsmv/soap.rb +0 -2
  50. data/lib/winrm/wsmv/wql_pull.rb +54 -56
  51. data/lib/winrm/wsmv/wql_query.rb +98 -99
  52. data/lib/winrm/wsmv/write_stdin.rb +0 -2
  53. data/lib/winrm.rb +3 -5
  54. metadata +81 -135
  55. data/.gitignore +0 -10
  56. data/.rubocop.yml +0 -26
  57. data/.travis.yml +0 -11
  58. data/Gemfile +0 -3
  59. data/Rakefile +0 -34
  60. data/Vagrantfile +0 -6
  61. data/WinrmAppveyor.psm1 +0 -32
  62. data/appveyor.yml +0 -51
  63. data/changelog.md +0 -128
  64. data/preamble +0 -17
  65. data/tests/integration/auth_timeout_spec.rb +0 -18
  66. data/tests/integration/cmd_spec.rb +0 -131
  67. data/tests/integration/config-example.yml +0 -16
  68. data/tests/integration/issue_59_spec.rb +0 -26
  69. data/tests/integration/powershell_spec.rb +0 -165
  70. data/tests/integration/spec_helper.rb +0 -65
  71. data/tests/integration/transport_spec.rb +0 -99
  72. data/tests/integration/wql_spec.rb +0 -34
  73. data/tests/matchers.rb +0 -60
  74. data/tests/spec/configuration_spec.rb +0 -184
  75. data/tests/spec/connection_spec.rb +0 -39
  76. data/tests/spec/exception_spec.rb +0 -50
  77. data/tests/spec/http/transport_factory_spec.rb +0 -68
  78. data/tests/spec/http/transport_spec.rb +0 -44
  79. data/tests/spec/output_spec.rb +0 -127
  80. data/tests/spec/psrp/fragment_spec.rb +0 -62
  81. data/tests/spec/psrp/message_data/base_spec.rb +0 -13
  82. data/tests/spec/psrp/message_data/error_record_spec.rb +0 -41
  83. data/tests/spec/psrp/message_data/pipeline_host_call_spec.rb +0 -25
  84. data/tests/spec/psrp/message_data/pipeline_output_spec.rb +0 -32
  85. data/tests/spec/psrp/message_data/pipeline_state_spec.rb +0 -40
  86. data/tests/spec/psrp/message_data/runspace_pool_host_call_spec.rb +0 -25
  87. data/tests/spec/psrp/message_data/runspacepool_state_spec.rb +0 -16
  88. data/tests/spec/psrp/message_data/session_capability_spec.rb +0 -30
  89. data/tests/spec/psrp/message_data_spec.rb +0 -35
  90. data/tests/spec/psrp/message_defragmenter_spec.rb +0 -47
  91. data/tests/spec/psrp/message_fragmenter_spec.rb +0 -105
  92. data/tests/spec/psrp/powershell_output_decoder_spec.rb +0 -100
  93. data/tests/spec/psrp/psrp_message_spec.rb +0 -70
  94. data/tests/spec/psrp/recieve_response_reader_spec.rb +0 -172
  95. data/tests/spec/psrp/uuid_spec.rb +0 -28
  96. data/tests/spec/response_handler_spec.rb +0 -61
  97. data/tests/spec/shells/base_spec.rb +0 -225
  98. data/tests/spec/shells/cmd_spec.rb +0 -75
  99. data/tests/spec/shells/powershell_spec.rb +0 -175
  100. data/tests/spec/spec_helper.rb +0 -47
  101. data/tests/spec/stubs/clixml/error_record.xml.erb +0 -84
  102. data/tests/spec/stubs/clixml/pipeline_state.xml.erb +0 -88
  103. data/tests/spec/stubs/responses/get_command_output_response.xml.erb +0 -13
  104. data/tests/spec/stubs/responses/get_command_output_response_not_done.xml.erb +0 -10
  105. data/tests/spec/stubs/responses/get_powershell_keepalive_response.xml.erb +0 -10
  106. data/tests/spec/stubs/responses/get_powershell_output_response.xml.erb +0 -12
  107. data/tests/spec/stubs/responses/get_powershell_output_response_not_done.xml.erb +0 -9
  108. data/tests/spec/stubs/responses/open_shell_v1.xml +0 -19
  109. data/tests/spec/stubs/responses/open_shell_v2.xml +0 -20
  110. data/tests/spec/stubs/responses/soap_fault_v1.xml +0 -36
  111. data/tests/spec/stubs/responses/soap_fault_v2.xml +0 -42
  112. data/tests/spec/stubs/responses/wmi_error_v2.xml +0 -41
  113. data/tests/spec/wsmv/cleanup_command_spec.rb +0 -22
  114. data/tests/spec/wsmv/close_shell_spec.rb +0 -17
  115. data/tests/spec/wsmv/command_output_decoder_spec.rb +0 -37
  116. data/tests/spec/wsmv/command_output_spec.rb +0 -45
  117. data/tests/spec/wsmv/command_spec.rb +0 -19
  118. data/tests/spec/wsmv/configuration_spec.rb +0 -17
  119. data/tests/spec/wsmv/create_pipeline_spec.rb +0 -31
  120. data/tests/spec/wsmv/create_shell_spec.rb +0 -38
  121. data/tests/spec/wsmv/init_runspace_pool_spec.rb +0 -36
  122. data/tests/spec/wsmv/keep_alive_spec.rb +0 -21
  123. data/tests/spec/wsmv/receive_response_reader_spec.rb +0 -123
  124. data/tests/spec/wsmv/send_data_spec.rb +0 -30
  125. data/tests/spec/wsmv/wql_query_spec.rb +0 -13
  126. data/tests/spec/wsmv/write_stdin_spec.rb +0 -22
  127. data/winrm.gemspec +0 -47
@@ -1,61 +0,0 @@
1
- # encoding: UTF-8
2
- require 'winrm/http/response_handler'
3
-
4
- describe 'response handler', unit: true do
5
- %w(v1 v2).each do |winrm_version|
6
- context "winrm_version #{winrm_version}" do
7
- let(:soap_fault) { stubbed_response("soap_fault_#{winrm_version}.xml") }
8
- let(:open_shell) { stubbed_response("open_shell_#{winrm_version}.xml") }
9
-
10
- describe "successful 200 #{winrm_version} response" do
11
- it 'returns an xml doc' do
12
- handler = WinRM::ResponseHandler.new(open_shell, 200)
13
- xml_doc = handler.parse_to_xml
14
- expect(xml_doc).to be_instance_of(REXML::Document)
15
- expect(xml_doc.to_s).to eq(REXML::Document.new(open_shell).to_s)
16
- end
17
- end
18
-
19
- describe "failed 500 #{winrm_version} response" do
20
- it 'raises a WinRMHTTPTransportError' do
21
- handler = WinRM::ResponseHandler.new('', 500)
22
- expect { handler.parse_to_xml }.to raise_error(WinRM::WinRMHTTPTransportError)
23
- end
24
- end
25
-
26
- describe "failed 401 #{winrm_version} response" do
27
- it 'raises a WinRMAuthorizationError' do
28
- handler = WinRM::ResponseHandler.new('', 401)
29
- expect { handler.parse_to_xml }.to raise_error(WinRM::WinRMAuthorizationError)
30
- end
31
- end
32
-
33
- describe "failed 400 #{winrm_version} response" do
34
- it 'raises a WinRMWSManFault' do
35
- handler = WinRM::ResponseHandler.new(soap_fault, 400)
36
- begin
37
- handler.parse_to_xml
38
- rescue WinRM::WinRMWSManFault => e
39
- expect(e.fault_code).to eq('2150858778')
40
- expect(e.fault_description).to include(
41
- 'The specified class does not exist in the given namespace')
42
- end
43
- end
44
- end
45
- end
46
- end
47
-
48
- describe 'failed 500 WMI error response' do
49
- let(:wmi_error) { stubbed_response('wmi_error_v2.xml') }
50
-
51
- it 'raises a WinRMWMIError' do
52
- handler = WinRM::ResponseHandler.new(wmi_error, 500)
53
- begin
54
- handler.parse_to_xml
55
- rescue WinRM::WinRMWMIError => e
56
- expect(e.error_code).to eq('2150859173')
57
- expect(e.error).to include('The WS-Management service cannot process the request.')
58
- end
59
- end
60
- end
61
- end
@@ -1,225 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'winrm/shells/base'
4
-
5
- # Dummy shell class
6
- class DummyShell < WinRM::Shells::Base
7
- class << self
8
- def finalize(connection_opts, transport, shell_id)
9
- proc { DummyShell.close_shell(connection_opts, transport, shell_id) }
10
- end
11
-
12
- def close_shell(_connection_opts, _transport, _shell_id)
13
- @closed = true
14
- end
15
-
16
- def closed?
17
- @closed
18
- end
19
- end
20
-
21
- def open_shell
22
- @closed = false
23
- 'shell_id'
24
- end
25
-
26
- def send_command(_command, _arguments)
27
- 'command_id'
28
- end
29
-
30
- def out_streams
31
- %w(std)
32
- end
33
- end
34
-
35
- describe DummyShell do
36
- let(:retry_limit) { 1 }
37
- let(:shell_id) { 'shell_id' }
38
- let(:output) { 'output' }
39
- let(:command_id) { 'command_id' }
40
- let(:payload) { 'message_payload' }
41
- let(:command) { 'command' }
42
- let(:arguments) { ['args'] }
43
- let(:output_message) { double('output_message', build: 'output_message') }
44
- let(:connection_options) { { max_commands: 100, retry_limit: retry_limit, retry_delay: 0 } }
45
- let(:transport) { double('transport') }
46
- let(:reader) { double('reader') }
47
-
48
- before do
49
- allow(subject).to receive(:response_reader).and_return(reader)
50
- allow(subject).to receive(:command_output_message).with(shell_id, command_id)
51
- .and_return(output_message)
52
- allow(reader).to receive(:read_output).with(output_message).and_return(output)
53
- allow(transport).to receive(:send_request)
54
- end
55
-
56
- subject { described_class.new(connection_options, transport, Logging.logger['test']) }
57
-
58
- shared_examples 'retry shell command' do
59
- it 'only closes the shell if there are too many' do
60
- if fault == WinRM::Shells::Base::TOO_MANY_COMMANDS
61
- expect(DummyShell).to receive(:close_shell)
62
- else
63
- expect(DummyShell).not_to receive(:close_shell)
64
- end
65
-
66
- subject.run(command, arguments)
67
- end
68
-
69
- it 'opens a new shell' do
70
- expect(subject).to receive(:open).and_call_original.twice
71
-
72
- subject.run(command, arguments)
73
- end
74
-
75
- it 'retries the command once' do
76
- expect(subject).to receive(:send_command).twice
77
-
78
- subject.run(command, arguments)
79
- end
80
- end
81
-
82
- describe '#run' do
83
- it 'opens a shell' do
84
- subject.run(command, arguments)
85
- expect(subject.shell_id).not_to be nil
86
- end
87
-
88
- it 'returns output from generated command' do
89
- expect(subject.run(command, arguments)).to eq output
90
- end
91
-
92
- it 'sends cleanup message through transport' do
93
- allow(SecureRandom).to receive(:uuid).and_return('uuid')
94
- expect(transport).to receive(:send_request)
95
- .with(
96
- WinRM::WSMV::CleanupCommand.new(
97
- connection_options,
98
- shell_uri: nil,
99
- shell_id: shell_id,
100
- command_id: command_id
101
- ).build
102
- )
103
- subject.run(command, arguments)
104
- end
105
-
106
- it 'does not error if cleanup is aborted' do
107
- allow(SecureRandom).to receive(:uuid).and_return('uuid')
108
- expect(transport).to receive(:send_request)
109
- .with(
110
- WinRM::WSMV::CleanupCommand.new(
111
- connection_options,
112
- shell_uri: nil,
113
- shell_id: shell_id,
114
- command_id: command_id
115
- ).build
116
- ).and_raise(WinRM::WinRMWSManFault.new('oops', '995'))
117
- subject.run(command, arguments)
118
- end
119
-
120
- it 'does not error if shell is not present anymore' do
121
- allow(SecureRandom).to receive(:uuid).and_return('uuid')
122
- expect(transport).to receive(:send_request)
123
- .with(
124
- WinRM::WSMV::CleanupCommand.new(
125
- connection_options,
126
- shell_uri: nil,
127
- shell_id: shell_id,
128
- command_id: command_id
129
- ).build
130
- ).and_raise(WinRM::WinRMWSManFault.new('oops', '2150858843'))
131
- subject.run(command, arguments)
132
- end
133
-
134
- it 'opens a shell only once when shell is already open' do
135
- expect(subject).to receive(:open_shell).and_call_original.once
136
- subject.run(command, arguments)
137
- subject.run(command, arguments)
138
- end
139
-
140
- describe 'connection resets' do
141
- before do
142
- @times_called = 0
143
-
144
- allow(subject).to receive(:send_command) do
145
- @times_called += 1
146
- raise WinRM::WinRMWSManFault.new('oops', fault) if @times_called == 1
147
- command_id
148
- end
149
- end
150
-
151
- context 'when shell is closed on server' do
152
- let(:fault) { '2150858843' }
153
-
154
- include_examples 'retry shell command'
155
- end
156
-
157
- context 'when shell accesses a deleted registry key' do
158
- let(:fault) { '2147943418' }
159
-
160
- include_examples 'retry shell command'
161
- end
162
-
163
- context 'when maximum number of concurrent shells is exceeded' do
164
- let(:fault) { '2150859174' }
165
-
166
- include_examples 'retry shell command'
167
- end
168
- end
169
-
170
- context 'open_shell fails' do
171
- let(:retry_limit) { 2 }
172
- let(:output_message2) { double('message') }
173
-
174
- it 'retries and raises failure if it never succeeds' do
175
- expect(subject).to receive(:open_shell)
176
- .and_raise(Errno::ECONNREFUSED).exactly(retry_limit).times
177
- expect { subject.run(command) }.to raise_error(Errno::ECONNREFUSED)
178
- end
179
-
180
- it 'retries and returns shell on success' do
181
- @times = 0
182
- allow(subject).to receive(:command_output_message).with('shell_id 2', command_id)
183
- .and_return(output_message2)
184
- allow(reader).to receive(:read_output)
185
- .with(output_message2).and_return(output)
186
- allow(subject).to receive(:open_shell) do
187
- @times += 1
188
- raise(Errno::ECONNREFUSED) if @times == 1
189
- "shell_id #{@times}"
190
- end
191
-
192
- subject.run(command, arguments)
193
- expect(subject.shell_id).to eq 'shell_id 2'
194
- end
195
- end
196
- end
197
-
198
- describe '#close' do
199
- it 'does not close if not opened' do
200
- expect(DummyShell).not_to receive(:close_shell)
201
- subject.close
202
- end
203
-
204
- it 'close shell if opened' do
205
- subject.run(command, arguments)
206
- subject.close
207
- expect(DummyShell.closed?).to be(true)
208
- end
209
-
210
- it 'nils out the shell_id' do
211
- subject.run(command, arguments)
212
- subject.close
213
- expect(subject.shell_id).to be(nil)
214
- end
215
-
216
- context 'when shell was not found' do
217
- it 'does not raise' do
218
- subject.run(command, arguments)
219
- expect(DummyShell).to receive(:close_shell)
220
- .and_raise(WinRM::WinRMWSManFault.new('oops', '2150858843'))
221
- expect { subject.close }.not_to raise_error
222
- end
223
- end
224
- end
225
- end
@@ -1,75 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'winrm/shells/cmd'
4
-
5
- describe WinRM::Shells::Cmd do
6
- let(:retry_limit) { 1 }
7
- let(:shell_id) { 'shell_id' }
8
- let(:output) { 'output' }
9
- let(:create_shell_payload) { 'create_shell_payload' }
10
- let(:close_shell_payload) { 'close_shell_payload' }
11
- let(:cleanup_payload) { 'cleanup_payload' }
12
- let(:command) { 'run this command' }
13
- let(:arguments) { ['args'] }
14
- let(:command_response) { "<a xmlns:rsp='foo'><rsp:CommandId>command_id</rsp:CommandId></a>" }
15
- let(:connection_options) { { max_commands: 100, retry_limit: retry_limit, retry_delay: 0 } }
16
- let(:transport) { double('transport', send_request: nil) }
17
-
18
- before do
19
- allow_any_instance_of(WinRM::WSMV::CloseShell).to receive(:build)
20
- .and_return(close_shell_payload)
21
- allow_any_instance_of(WinRM::WSMV::CreateShell).to receive(:build)
22
- .and_return(create_shell_payload)
23
- allow_any_instance_of(WinRM::WSMV::CleanupCommand).to receive(:build)
24
- .and_return(cleanup_payload)
25
- allow_any_instance_of(WinRM::WSMV::ReceiveResponseReader).to receive(:read_output)
26
- .and_return(output)
27
- allow(transport).to receive(:send_request).with(create_shell_payload)
28
- .and_return(REXML::Document.new("<blah Name='ShellId'>#{shell_id}</blah>"))
29
- allow(transport).to receive(:send_request).with(/#{command}/)
30
- .and_return(REXML::Document.new(command_response))
31
- end
32
-
33
- subject { described_class.new(connection_options, transport, Logging.logger['test']) }
34
-
35
- describe '#run' do
36
- it 'opens a shell and gets shell id' do
37
- subject.run(command, arguments)
38
- expect(subject.shell_id).to eq shell_id
39
- end
40
-
41
- it 'sends create shell through transport' do
42
- expect(transport).to receive(:send_request).with(create_shell_payload)
43
- subject.run(command, arguments)
44
- end
45
-
46
- it 'returns output from generated command' do
47
- expect(subject.run(command, arguments)).to eq output
48
- end
49
-
50
- it 'sends command through transport' do
51
- expect(transport).to receive(:send_request).with(/#{command}/)
52
- subject.run(command, arguments)
53
- end
54
-
55
- it 'sends cleanup message through transport' do
56
- expect(transport).to receive(:send_request).with(cleanup_payload)
57
- subject.run(command, arguments)
58
- end
59
- end
60
-
61
- describe '#close' do
62
- it 'sends close shell through transport' do
63
- subject.run(command, arguments)
64
- expect(transport).to receive(:send_request).with(close_shell_payload)
65
- subject.close
66
- end
67
-
68
- it 'creates a shell closer with default shell uri' do
69
- allow(WinRM::WSMV::CloseShell).to receive(:new) do |_, opts|
70
- expect(opts[:shell_uri]).to be nil
71
- end.and_call_original
72
- subject.close
73
- end
74
- end
75
- end
@@ -1,175 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'winrm/shells/power_shell'
4
-
5
- describe WinRM::Shells::Powershell do
6
- let(:retry_limit) { 1 }
7
- let(:max_envelope_size_kb) { 150 }
8
- let(:shell_id) { 'bc1bfbba-8215-4a04-b2df-7a3ac0310e16' }
9
- let(:output) { 'output' }
10
- let(:command_id) { '4218A578-0F18-4B19-82C3-46B433319126' }
11
- let(:keepalive_payload) { 'keepalive_payload' }
12
- let(:configuration_payload) { 'configuration_payload' }
13
- let(:command_payload) { 'command_payload' }
14
- let(:create_shell_payload) { 'create_shell_payload' }
15
- let(:close_shell_payload) { 'close_shell_payload' }
16
- let(:cleanup_payload) { 'cleanup_payload' }
17
- let(:command) { 'command' }
18
- let(:output_message) { double('output_message', build: 'output_message') }
19
- let(:command_response) { "<a xmlns:rsp='foo'><rsp:CommandId>#{command_id}</rsp:CommandId></a>" }
20
- let(:configuration_response) do
21
- "<a xmlns:cfg='foo'><cfg:MaxEnvelopeSizekb>#{max_envelope_size_kb}</cfg:MaxEnvelopeSizekb></a>"
22
- end
23
- let(:connection_options) { { max_commands: 100, retry_limit: retry_limit, retry_delay: 0 } }
24
- let(:transport) { double('transport', send_request: nil) }
25
- let(:test_data_xml_template) do
26
- ERB.new(stubbed_response('get_powershell_keepalive_response.xml.erb'))
27
- end
28
- let(:protocol_version) { 2.2 }
29
- let(:test_data1) do
30
- <<-EOH
31
- <Obj RefId="0">
32
- <MS>
33
- <Version N="protocolversion">#{protocol_version}</Version>
34
- <Version N="PSVersion">2.0</Version>
35
- <Version N="SerializationVersion">1.1.0.1</Version>
36
- </MS>
37
- </Obj>
38
- EOH
39
- end
40
- let(:test_data2) { '<Obj RefId="0"><MS><I32 N="RunspaceState">2</I32></MS></Obj>' }
41
- let(:message1) do
42
- WinRM::PSRP::Message.new(
43
- shell_id,
44
- WinRM::PSRP::Message::MESSAGE_TYPES[:session_capability],
45
- test_data1,
46
- command_id
47
- )
48
- end
49
- let(:message2) do
50
- WinRM::PSRP::Message.new(
51
- shell_id,
52
- WinRM::PSRP::Message::MESSAGE_TYPES[:runspacepool_state],
53
- test_data2,
54
- command_id
55
- )
56
- end
57
- let(:fragment1) { WinRM::PSRP::Fragment.new(1, message1.bytes) }
58
- let(:fragment2) { WinRM::PSRP::Fragment.new(1, message2.bytes) }
59
- let(:test_data_stdout1) { Base64.strict_encode64(fragment1.bytes.pack('C*')) }
60
- let(:test_data_stdout2) { Base64.strict_encode64(fragment2.bytes.pack('C*')) }
61
-
62
- before do
63
- allow(SecureRandom).to receive(:uuid).and_return(command_id)
64
- allow(subject).to receive(:command_output_message).with(shell_id, command_id)
65
- .and_return(output_message)
66
- allow_any_instance_of(WinRM::WSMV::CreatePipeline).to receive(:build)
67
- .and_return(command_payload)
68
- allow_any_instance_of(WinRM::WSMV::CloseShell).to receive(:build)
69
- .and_return(close_shell_payload)
70
- allow_any_instance_of(WinRM::WSMV::InitRunspacePool).to receive(:build)
71
- .and_return(create_shell_payload)
72
- allow_any_instance_of(WinRM::WSMV::Configuration).to receive(:build)
73
- .and_return(configuration_payload)
74
- allow_any_instance_of(WinRM::WSMV::CleanupCommand).to receive(:build)
75
- .and_return(cleanup_payload)
76
- allow_any_instance_of(WinRM::WSMV::KeepAlive).to receive(:build).and_return(keepalive_payload)
77
- allow_any_instance_of(WinRM::PSRP::ReceiveResponseReader).to receive(:read_output)
78
- .with(output_message).and_return(output)
79
- allow(transport).to receive(:send_request).with(configuration_payload).and_return(
80
- REXML::Document.new(configuration_response))
81
- allow(transport).to receive(:send_request).with(create_shell_payload)
82
- .and_return(REXML::Document.new("<blah Name='ShellId'>#{shell_id}</blah>"))
83
- allow(transport).to receive(:send_request).with(command_payload)
84
- .and_return(REXML::Document.new(command_response))
85
- allow(transport).to receive(:send_request).with(keepalive_payload)
86
- .and_return(REXML::Document.new(test_data_xml_template.result(binding)))
87
- end
88
-
89
- subject { described_class.new(connection_options, transport, Logging.logger['test']) }
90
-
91
- describe '#run' do
92
- it 'opens a shell and gets shell id' do
93
- subject.run(command)
94
- expect(subject.shell_id).to eq shell_id
95
- end
96
-
97
- it 'sends create shell through transport' do
98
- expect(transport).to receive(:send_request).with(create_shell_payload)
99
- subject.run(command)
100
- end
101
-
102
- it 'sends keepalive shell through transport' do
103
- expect(transport).to receive(:send_request).with(keepalive_payload)
104
- subject.run(command)
105
- end
106
-
107
- it 'returns output from generated command' do
108
- expect(subject.run(command)).to eq output
109
- end
110
-
111
- it 'sends command through transport' do
112
- expect(transport).to receive(:send_request).with(command_payload)
113
- subject.run(command)
114
- end
115
-
116
- it 'sends cleanup message through transport' do
117
- expect(transport).to receive(:send_request).with(cleanup_payload)
118
- subject.run(command)
119
- end
120
-
121
- context 'non admin user' do
122
- before do
123
- allow(transport).to receive(:send_request).with(configuration_payload)
124
- .and_raise(WinRM::WinRMWSManFault.new('no access for you', '5'))
125
- end
126
-
127
- context 'protocol version 2.1' do
128
- let(:protocol_version) { 2.1 }
129
-
130
- it 'sets the fragmenter max_blob_length' do
131
- expect_any_instance_of(WinRM::PSRP::MessageFragmenter).to receive(:max_blob_length=)
132
- .with(153600)
133
- subject.run(command)
134
- end
135
- end
136
-
137
- context 'protocol version 2.2' do
138
- let(:protocol_version) { 2.2 }
139
-
140
- it 'sets the fragmenter max_blob_length' do
141
- expect_any_instance_of(WinRM::PSRP::MessageFragmenter).to receive(:max_blob_length=)
142
- .with(512000)
143
- subject.run(command)
144
- end
145
- end
146
- end
147
-
148
- context 'fragment large command' do
149
- let(:command) { 'c' * 200000 }
150
-
151
- it 'fragments messages as large as max envelope size' do
152
- allow_any_instance_of(WinRM::WSMV::CreatePipeline).to receive(:build).and_call_original
153
- allow(transport).to receive(:send_request).with(/CommandLine/) do |payload|
154
- expect(payload.length).to be max_envelope_size_kb * 1024
155
- end.and_return(REXML::Document.new(command_response))
156
- subject.run(command)
157
- end
158
- end
159
- end
160
-
161
- describe '#close' do
162
- it 'sends close shell through transport' do
163
- subject.run(command)
164
- expect(transport).to receive(:send_request).with(close_shell_payload)
165
- subject.close
166
- end
167
-
168
- it 'creates a shell closer with powershell uri' do
169
- allow(WinRM::WSMV::CloseShell).to receive(:new) do |_, opts|
170
- expect(opts[:shell_uri]).to be WinRM::WSMV::Header::RESOURCE_URI_POWERSHELL
171
- end.and_call_original
172
- subject.close
173
- end
174
- end
175
- end
@@ -1,47 +0,0 @@
1
- # encoding: UTF-8
2
- require 'rubygems'
3
- require 'bundler/setup'
4
- require 'winrm'
5
- require 'json'
6
- require_relative '../matchers'
7
-
8
- # Unit test spec helper
9
- module SpecUnitHelper
10
- def stubbed_response(file)
11
- File.read("tests/spec/stubs/responses/#{file}")
12
- end
13
-
14
- def stubbed_clixml(file)
15
- File.read("tests/spec/stubs/clixml/#{file}")
16
- end
17
-
18
- def default_connection_opts
19
- {
20
- user: 'Administrator',
21
- password: 'password',
22
- endpoint: 'http://localhost:5985/wsman',
23
- max_envelope_size: 153600,
24
- session_id: '05A2622B-B842-4EB8-8A78-0225C8A993DF',
25
- operation_timeout: 60,
26
- locale: 'en-US'
27
- }
28
- end
29
- end
30
-
31
- # Strip leading whitespace from each line that is the same as the
32
- # amount of whitespace on the first line of the string.
33
- # Leaves _additional_ indentation on later lines intact.
34
- # and remove newlines.
35
- class String
36
- def unindent
37
- gsub(/^#{self[/\A[ \t]*/]}/, '').delete("\n")
38
- end
39
-
40
- def to_byte_string
41
- force_encoding(Encoding::ASCII_8BIT)
42
- end
43
- end
44
-
45
- RSpec.configure do |config|
46
- config.include(SpecUnitHelper)
47
- end
@@ -1,84 +0,0 @@
1
- <?xml version="1.0"?>
2
- <Obj RefId="0">
3
- <TN RefId="0">
4
- <T>System.Management.Automation.ErrorRecord</T>
5
- <T>System.Object</T>
6
- </TN>
7
- <ToString><%= error_message %></ToString>
8
- <MS>
9
- <B N="writeErrorStream">true</B>
10
- <Obj N="Exception" RefId="1">
11
- <TN RefId="1">
12
- <T>Microsoft.PowerShell.Commands.WriteErrorException</T>
13
- <T>Microsoft.PowerShell.CoreClr.Stubs.SystemException</T>
14
- <T>System.Exception</T>
15
- <T>System.Object</T>
16
- </TN>
17
- <ToString>Microsoft.PowerShell.Commands.WriteErrorException: <%= error_message %></ToString>
18
- <Props>
19
- <S N="Message"><%= error_message %></S>
20
- <Obj N="Data" RefId="2">
21
- <TN RefId="2">
22
- <T>System.Collections.ListDictionaryInternal</T>
23
- <T>System.Object</T>
24
- </TN>
25
- <DCT/>
26
- </Obj>
27
- <Nil N="InnerException"/>
28
- <Nil N="StackTrace"/>
29
- <Nil N="HelpLink"/>
30
- <Nil N="Source"/>
31
- <I32 N="HResult">-2146233088</I32>
32
- </Props>
33
- </Obj>
34
- <Nil N="TargetObject"/>
35
- <S N="FullyQualifiedErrorId"><%= error_id %></S>
36
- <Obj N="InvocationInfo" RefId="3">
37
- <TN RefId="3">
38
- <T>System.Management.Automation.InvocationInfo</T>
39
- <T>System.Object</T>
40
- </TN>
41
- <ToString>System.Management.Automation.InvocationInfo</ToString>
42
- <Props>
43
- <Nil N="MyCommand"/>
44
- <Obj N="BoundParameters" RefId="4">
45
- <TN RefId="4">
46
- <T>System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]</T>
47
- <T>System.Object</T>
48
- </TN>
49
- <DCT/>
50
- </Obj>
51
- <Obj N="UnboundArguments" RefId="5">
52
- <TN RefId="5">
53
- <T>System.Collections.Generic.List`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]</T>
54
- <T>System.Object</T>
55
- </TN>
56
- <LST/>
57
- </Obj>
58
- <I32 N="ScriptLineNumber">1</I32>
59
- <I32 N="OffsetInLine">1</I32>
60
- <I64 N="HistoryId">1</I64>
61
- <S N="ScriptName"/>
62
- <S N="Line">write-error '<%= error_message %>'</S>
63
- <S N="PositionMessage">At line:1 char:1_x000D__x000A_+ write-error '<%= error_message %>'_x000D__x000A_+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</S>
64
- <S N="PSScriptRoot"><%= script_root %></S>
65
- <Nil N="PSCommandPath"/>
66
- <S N="InvocationName"/>
67
- <I32 N="PipelineLength">0</I32>
68
- <I32 N="PipelinePosition">0</I32>
69
- <B N="ExpectingInput">false</B>
70
- <S N="CommandOrigin">Internal</S>
71
- <Nil N="DisplayScriptPosition"/>
72
- </Props>
73
- </Obj>
74
- <I32 N="ErrorCategory_Category">0</I32>
75
- <S N="ErrorCategory_Activity">Write-Error</S>
76
- <S N="ErrorCategory_Reason">WriteErrorException</S>
77
- <S N="ErrorCategory_TargetName"/>
78
- <S N="ErrorCategory_TargetType"/>
79
- <S N="ErrorCategory_Message"><%= category_message %></S>
80
- <B N="SerializeExtendedInfo">false</B>
81
- <S N="ErrorDetails_ScriptStackTrace"><%= stack_trace %></S>
82
- <Nil N="PSMessageDetails"/>
83
- </MS>
84
- </Obj>