winrm 2.3.0 → 2.3.5

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/lib/winrm/http/response_handler.rb +1 -1
  3. data/lib/winrm/http/transport.rb +2 -2
  4. data/lib/winrm/psrp/message.rb +128 -128
  5. data/lib/winrm/psrp/message_data/error_record.rb +2 -0
  6. data/lib/winrm/psrp/message_data/pipeline_output.rb +1 -1
  7. data/lib/winrm/psrp/message_factory.rb +14 -2
  8. data/lib/winrm/psrp/powershell_output_decoder.rb +142 -142
  9. data/lib/winrm/shells/base.rb +1 -0
  10. data/lib/winrm/shells/power_shell.rb +4 -4
  11. data/lib/winrm/version.rb +1 -1
  12. metadata +16 -90
  13. data/.gitignore +0 -10
  14. data/.rubocop.yml +0 -38
  15. data/.travis.yml +0 -10
  16. data/Gemfile +0 -2
  17. data/Rakefile +0 -33
  18. data/Vagrantfile +0 -6
  19. data/WinrmAppveyor.psm1 +0 -32
  20. data/appveyor.yml +0 -50
  21. data/changelog.md +0 -133
  22. data/preamble +0 -17
  23. data/tests/integration/auth_timeout_spec.rb +0 -17
  24. data/tests/integration/cmd_spec.rb +0 -130
  25. data/tests/integration/config-example.yml +0 -16
  26. data/tests/integration/issue_59_spec.rb +0 -25
  27. data/tests/integration/powershell_spec.rb +0 -164
  28. data/tests/integration/spec_helper.rb +0 -62
  29. data/tests/integration/transport_spec.rb +0 -98
  30. data/tests/integration/wql_spec.rb +0 -33
  31. data/tests/matchers.rb +0 -59
  32. data/tests/spec/configuration_spec.rb +0 -183
  33. data/tests/spec/connection_spec.rb +0 -37
  34. data/tests/spec/exception_spec.rb +0 -49
  35. data/tests/spec/http/transport_factory_spec.rb +0 -66
  36. data/tests/spec/http/transport_spec.rb +0 -43
  37. data/tests/spec/output_spec.rb +0 -128
  38. data/tests/spec/psrp/fragment_spec.rb +0 -60
  39. data/tests/spec/psrp/message_data/base_spec.rb +0 -11
  40. data/tests/spec/psrp/message_data/error_record_spec.rb +0 -39
  41. data/tests/spec/psrp/message_data/pipeline_host_call_spec.rb +0 -23
  42. data/tests/spec/psrp/message_data/pipeline_output_spec.rb +0 -30
  43. data/tests/spec/psrp/message_data/pipeline_state_spec.rb +0 -38
  44. data/tests/spec/psrp/message_data/runspace_pool_host_call_spec.rb +0 -23
  45. data/tests/spec/psrp/message_data/runspacepool_state_spec.rb +0 -14
  46. data/tests/spec/psrp/message_data/session_capability_spec.rb +0 -28
  47. data/tests/spec/psrp/message_data_spec.rb +0 -33
  48. data/tests/spec/psrp/message_defragmenter_spec.rb +0 -45
  49. data/tests/spec/psrp/message_fragmenter_spec.rb +0 -103
  50. data/tests/spec/psrp/powershell_output_decoder_spec.rb +0 -98
  51. data/tests/spec/psrp/psrp_message_spec.rb +0 -73
  52. data/tests/spec/psrp/recieve_response_reader_spec.rb +0 -170
  53. data/tests/spec/psrp/uuid_spec.rb +0 -28
  54. data/tests/spec/response_handler_spec.rb +0 -69
  55. data/tests/spec/shells/base_spec.rb +0 -227
  56. data/tests/spec/shells/cmd_spec.rb +0 -75
  57. data/tests/spec/shells/powershell_spec.rb +0 -221
  58. data/tests/spec/spec_helper.rb +0 -46
  59. data/tests/spec/stubs/clixml/error_record.xml.erb +0 -84
  60. data/tests/spec/stubs/clixml/pipeline_state.xml.erb +0 -88
  61. data/tests/spec/stubs/responses/get_command_output_response.xml.erb +0 -13
  62. data/tests/spec/stubs/responses/get_command_output_response_not_done.xml.erb +0 -10
  63. data/tests/spec/stubs/responses/get_omi_command_output_response.xml.erb +0 -23
  64. data/tests/spec/stubs/responses/get_omi_command_output_response_not_done.xml.erb +0 -24
  65. data/tests/spec/stubs/responses/get_omi_config_response.xml +0 -45
  66. data/tests/spec/stubs/responses/get_omi_powershell_keepalive_response.xml.erb +0 -33
  67. data/tests/spec/stubs/responses/get_powershell_keepalive_response.xml.erb +0 -10
  68. data/tests/spec/stubs/responses/get_powershell_output_response.xml.erb +0 -12
  69. data/tests/spec/stubs/responses/get_powershell_output_response_not_done.xml.erb +0 -9
  70. data/tests/spec/stubs/responses/open_shell_omi.xml +0 -43
  71. data/tests/spec/stubs/responses/open_shell_v1.xml +0 -19
  72. data/tests/spec/stubs/responses/open_shell_v2.xml +0 -20
  73. data/tests/spec/stubs/responses/soap_fault_omi.xml +0 -31
  74. data/tests/spec/stubs/responses/soap_fault_v1.xml +0 -36
  75. data/tests/spec/stubs/responses/soap_fault_v2.xml +0 -42
  76. data/tests/spec/stubs/responses/wmi_error_v2.xml +0 -41
  77. data/tests/spec/wsmv/cleanup_command_spec.rb +0 -20
  78. data/tests/spec/wsmv/close_shell_spec.rb +0 -15
  79. data/tests/spec/wsmv/command_output_decoder_spec.rb +0 -35
  80. data/tests/spec/wsmv/command_output_spec.rb +0 -43
  81. data/tests/spec/wsmv/command_spec.rb +0 -17
  82. data/tests/spec/wsmv/configuration_spec.rb +0 -15
  83. data/tests/spec/wsmv/create_pipeline_spec.rb +0 -30
  84. data/tests/spec/wsmv/create_shell_spec.rb +0 -39
  85. data/tests/spec/wsmv/init_runspace_pool_spec.rb +0 -38
  86. data/tests/spec/wsmv/keep_alive_spec.rb +0 -21
  87. data/tests/spec/wsmv/receive_response_reader_spec.rb +0 -124
  88. data/tests/spec/wsmv/send_data_spec.rb +0 -30
  89. data/tests/spec/wsmv/wql_query_spec.rb +0 -11
  90. data/tests/spec/wsmv/write_stdin_spec.rb +0 -20
  91. data/winrm.gemspec +0 -46
@@ -1,69 +0,0 @@
1
- require 'winrm/http/response_handler'
2
-
3
- describe 'response handler', unit: true do
4
- %w[v1 v2 omi].each do |winrm_version|
5
- context "winrm_version #{winrm_version}" do
6
- let(:soap_fault) { stubbed_response("soap_fault_#{winrm_version}.xml") }
7
- let(:open_shell) { stubbed_response("open_shell_#{winrm_version}.xml") }
8
-
9
- describe "successful 200 #{winrm_version} response" do
10
- it 'returns an xml doc' do
11
- handler = WinRM::ResponseHandler.new(open_shell, 200)
12
- xml_doc = handler.parse_to_xml
13
- expect(xml_doc).to be_instance_of(REXML::Document)
14
- expect(xml_doc.to_s).to eq(REXML::Document.new(open_shell).to_s)
15
- end
16
- end
17
-
18
- describe "failed 500 #{winrm_version} response" do
19
- it 'raises a WinRMHTTPTransportError' do
20
- handler = WinRM::ResponseHandler.new('', 500)
21
- expect { handler.parse_to_xml }.to raise_error(WinRM::WinRMHTTPTransportError)
22
- end
23
- end
24
-
25
- describe "failed 401 #{winrm_version} response" do
26
- it 'raises a WinRMAuthorizationError' do
27
- handler = WinRM::ResponseHandler.new('', 401)
28
- expect { handler.parse_to_xml }.to raise_error(WinRM::WinRMAuthorizationError)
29
- end
30
- end
31
-
32
- describe "failed 400 #{winrm_version} response" do
33
- it 'raises a WinRMWSManFault' do
34
- handler = WinRM::ResponseHandler.new(soap_fault, 400)
35
- begin
36
- handler.parse_to_xml
37
- # PowerShell
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
- )
43
- # OMI
44
- rescue WinRM::WinRMSoapFault => e
45
- expect(e.code).to eq('SOAP-ENV:Receiver')
46
- expect(e.subcode).to eq('wsman:InternalError')
47
- expect(e.reason).to eq(
48
- 'get-instance: instance name parameter is missing'
49
- )
50
- end
51
- end
52
- end
53
- end
54
- end
55
-
56
- describe 'failed 500 WMI error response' do
57
- let(:wmi_error) { stubbed_response('wmi_error_v2.xml') }
58
-
59
- it 'raises a WinRMWMIError' do
60
- handler = WinRM::ResponseHandler.new(wmi_error, 500)
61
- begin
62
- handler.parse_to_xml
63
- rescue WinRM::WinRMWMIError => e
64
- expect(e.error_code).to eq('2150859173')
65
- expect(e.error).to include('The WS-Management service cannot process the request.')
66
- end
67
- end
68
- end
69
- end
@@ -1,227 +0,0 @@
1
- require 'winrm/shells/base'
2
-
3
- # Dummy shell class
4
- class DummyShell < WinRM::Shells::Base
5
- class << self
6
- def finalize(connection_opts, transport, shell_id)
7
- proc { DummyShell.close_shell(connection_opts, transport, shell_id) }
8
- end
9
-
10
- def close_shell(_connection_opts, _transport, _shell_id)
11
- @closed = true
12
- end
13
-
14
- def closed?
15
- @closed
16
- end
17
- end
18
-
19
- def open_shell
20
- @closed = false
21
- 'shell_id'
22
- end
23
-
24
- def send_command(_command, _arguments)
25
- 'command_id'
26
- end
27
-
28
- def out_streams
29
- %w[std]
30
- end
31
- end
32
-
33
- describe DummyShell do
34
- let(:retry_limit) { 1 }
35
- let(:shell_id) { 'shell_id' }
36
- let(:output) { 'output' }
37
- let(:command_id) { 'command_id' }
38
- let(:payload) { 'message_payload' }
39
- let(:command) { 'command' }
40
- let(:arguments) { ['args'] }
41
- let(:output_message) { double('output_message', build: 'output_message') }
42
- let(:connection_options) { { max_commands: 100, retry_limit: retry_limit, retry_delay: 0 } }
43
- let(:transport) { double('transport') }
44
- let(:reader) { double('reader') }
45
-
46
- before do
47
- allow(subject).to receive(:response_reader).and_return(reader)
48
- allow(subject).to receive(:command_output_message)
49
- .with(shell_id, command_id)
50
- .and_return(output_message)
51
- allow(reader).to receive(:read_output).with(output_message).and_return(output)
52
- allow(transport).to receive(:send_request)
53
- end
54
-
55
- subject { described_class.new(connection_options, transport, Logging.logger['test']) }
56
-
57
- shared_examples 'retry shell command' do
58
- it 'only closes the shell if there are too many' do
59
- if fault == WinRM::Shells::Base::TOO_MANY_COMMANDS
60
- expect(DummyShell).to receive(:close_shell)
61
- else
62
- expect(DummyShell).not_to receive(:close_shell)
63
- end
64
-
65
- subject.run(command, arguments)
66
- end
67
-
68
- it 'opens a new shell' do
69
- expect(subject).to receive(:open).and_call_original.twice
70
-
71
- subject.run(command, arguments)
72
- end
73
-
74
- it 'retries the command once' do
75
- expect(subject).to receive(:send_command).twice
76
-
77
- subject.run(command, arguments)
78
- end
79
- end
80
-
81
- describe '#run' do
82
- it 'opens a shell' do
83
- subject.run(command, arguments)
84
- expect(subject.shell_id).not_to be nil
85
- end
86
-
87
- it 'returns output from generated command' do
88
- expect(subject.run(command, arguments)).to eq output
89
- end
90
-
91
- it 'sends cleanup message through transport' do
92
- allow(SecureRandom).to receive(:uuid).and_return('uuid')
93
- expect(transport).to receive(:send_request)
94
- .with(
95
- WinRM::WSMV::CleanupCommand.new(
96
- connection_options,
97
- shell_uri: nil,
98
- shell_id: shell_id,
99
- command_id: command_id
100
- ).build
101
- )
102
- subject.run(command, arguments)
103
- end
104
-
105
- it 'does not error if cleanup is aborted' do
106
- allow(SecureRandom).to receive(:uuid).and_return('uuid')
107
- expect(transport).to receive(:send_request)
108
- .with(
109
- WinRM::WSMV::CleanupCommand.new(
110
- connection_options,
111
- shell_uri: nil,
112
- shell_id: shell_id,
113
- command_id: command_id
114
- ).build
115
- ).and_raise(WinRM::WinRMWSManFault.new('oops', '995'))
116
- subject.run(command, arguments)
117
- end
118
-
119
- it 'does not error if shell is not present anymore' do
120
- allow(SecureRandom).to receive(:uuid).and_return('uuid')
121
- expect(transport).to receive(:send_request)
122
- .with(
123
- WinRM::WSMV::CleanupCommand.new(
124
- connection_options,
125
- shell_uri: nil,
126
- shell_id: shell_id,
127
- command_id: command_id
128
- ).build
129
- ).and_raise(WinRM::WinRMWSManFault.new('oops', '2150858843'))
130
- subject.run(command, arguments)
131
- end
132
-
133
- it 'opens a shell only once when shell is already open' do
134
- expect(subject).to receive(:open_shell).and_call_original.once
135
- subject.run(command, arguments)
136
- subject.run(command, arguments)
137
- end
138
-
139
- describe 'connection resets' do
140
- before do
141
- @times_called = 0
142
-
143
- allow(subject).to receive(:send_command) do
144
- @times_called += 1
145
- raise WinRM::WinRMWSManFault.new('oops', fault) if @times_called == 1
146
-
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)
183
- .with('shell_id 2', command_id)
184
- .and_return(output_message2)
185
- allow(reader).to receive(:read_output)
186
- .with(output_message2).and_return(output)
187
- allow(subject).to receive(:open_shell) do
188
- @times += 1
189
- raise(Errno::ECONNREFUSED) if @times == 1
190
-
191
- "shell_id #{@times}"
192
- end
193
-
194
- subject.run(command, arguments)
195
- expect(subject.shell_id).to eq 'shell_id 2'
196
- end
197
- end
198
- end
199
-
200
- describe '#close' do
201
- it 'does not close if not opened' do
202
- expect(DummyShell).not_to receive(:close_shell)
203
- subject.close
204
- end
205
-
206
- it 'close shell if opened' do
207
- subject.run(command, arguments)
208
- subject.close
209
- expect(DummyShell.closed?).to be(true)
210
- end
211
-
212
- it 'nils out the shell_id' do
213
- subject.run(command, arguments)
214
- subject.close
215
- expect(subject.shell_id).to be(nil)
216
- end
217
-
218
- context 'when shell was not found' do
219
- it 'does not raise' do
220
- subject.run(command, arguments)
221
- expect(DummyShell).to receive(:close_shell)
222
- .and_raise(WinRM::WinRMWSManFault.new('oops', '2150858843'))
223
- expect { subject.close }.not_to raise_error
224
- end
225
- end
226
- end
227
- end
@@ -1,75 +0,0 @@
1
- require 'winrm/shells/cmd'
2
-
3
- describe WinRM::Shells::Cmd do
4
- let(:retry_limit) { 1 }
5
- let(:shell_id) { 'shell_id' }
6
- let(:output) { 'output' }
7
- let(:create_shell_payload) { 'create_shell_payload' }
8
- let(:close_shell_payload) { 'close_shell_payload' }
9
- let(:cleanup_payload) { 'cleanup_payload' }
10
- let(:command) { 'run this command' }
11
- let(:arguments) { ['args'] }
12
- let(:command_response) { "<a xmlns:rsp='foo'><rsp:CommandId>command_id</rsp:CommandId></a>" }
13
- let(:connection_options) { { max_commands: 100, retry_limit: retry_limit, retry_delay: 0 } }
14
- let(:transport) { double('transport', send_request: nil) }
15
-
16
- before do
17
- allow_any_instance_of(WinRM::WSMV::CloseShell).to receive(:build)
18
- .and_return(close_shell_payload)
19
- allow_any_instance_of(WinRM::WSMV::CreateShell).to receive(:build)
20
- .and_return(create_shell_payload)
21
- allow_any_instance_of(WinRM::WSMV::CleanupCommand).to receive(:build)
22
- .and_return(cleanup_payload)
23
- allow_any_instance_of(WinRM::WSMV::ReceiveResponseReader).to receive(:read_output)
24
- .and_return(output)
25
- allow(transport).to receive(:send_request)
26
- .with(create_shell_payload)
27
- .and_return(REXML::Document.new("<blah Name='ShellId'>#{shell_id}</blah>"))
28
- allow(transport).to receive(:send_request)
29
- .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,221 +0,0 @@
1
- require 'winrm/shells/power_shell'
2
-
3
- describe WinRM::Shells::Powershell do
4
- let(:retry_limit) { 1 }
5
- let(:max_envelope_size_kb) { 150 }
6
- let(:shell_id) { 'bc1bfbba-8215-4a04-b2df-7a3ac0310e16' }
7
- let(:output) { 'output' }
8
- let(:command_id) { '4218A578-0F18-4B19-82C3-46B433319126' }
9
- let(:keepalive_payload) { 'keepalive_payload' }
10
- let(:configuration_payload) { 'configuration_payload' }
11
- let(:command_payload) { 'command_payload' }
12
- let(:create_shell_payload) { 'create_shell_payload' }
13
- let(:close_shell_payload) { 'close_shell_payload' }
14
- let(:cleanup_payload) { 'cleanup_payload' }
15
- let(:command) { 'command' }
16
- let(:output_message) { double('output_message', build: 'output_message') }
17
- let(:connection_options) { { max_commands: 100, retry_limit: retry_limit, retry_delay: 0 } }
18
- let(:transport) { double('transport', send_request: nil) }
19
- let(:protocol_version) { 2.2 }
20
- let(:test_data1) do
21
- <<-EOH
22
- <Obj RefId="0">
23
- <MS>
24
- <Version N="protocolversion">#{protocol_version}</Version>
25
- <Version N="PSVersion">2.0</Version>
26
- <Version N="SerializationVersion">1.1.0.1</Version>
27
- </MS>
28
- </Obj>
29
- EOH
30
- end
31
- let(:test_data2) { '<Obj RefId="0"><MS><I32 N="RunspaceState">2</I32></MS></Obj>' }
32
- let(:message1) do
33
- WinRM::PSRP::Message.new(
34
- shell_id,
35
- WinRM::PSRP::Message::MESSAGE_TYPES[:session_capability],
36
- test_data1,
37
- command_id
38
- )
39
- end
40
- let(:message2) do
41
- WinRM::PSRP::Message.new(
42
- shell_id,
43
- WinRM::PSRP::Message::MESSAGE_TYPES[:runspacepool_state],
44
- test_data2,
45
- command_id
46
- )
47
- end
48
- let(:fragment1) { WinRM::PSRP::Fragment.new(1, message1.bytes) }
49
- let(:fragment2) { WinRM::PSRP::Fragment.new(1, message2.bytes) }
50
- let(:test_data_stdout1) { Base64.strict_encode64(fragment1.bytes.pack('C*')) }
51
- let(:test_data_stdout2) { Base64.strict_encode64(fragment2.bytes.pack('C*')) }
52
-
53
- {
54
- 'powershell' => {
55
- keepalive_template_path: 'get_powershell_keepalive_response.xml.erb',
56
- config: "<a xmlns:cfg='f'><cfg:MaxEnvelopeSizekb>" \
57
- '<%= max_envelope_size_kb %></cfg:MaxEnvelopeSizekb></a>',
58
- command: "<a xmlns:rsp='foo'><rsp:CommandId><%= command_id %></rsp:CommandId></a>"
59
- },
60
- 'omi' => {
61
- keepalive_template_path: 'get_omi_powershell_keepalive_response.xml.erb',
62
- config: File.read('tests/spec/stubs/responses/get_omi_config_response.xml'),
63
- command: "<p:CommandResponse xmlns:p='foo'><p:CommandId>" \
64
- '<%= command_id %></p:CommandId></p:CommandResponse>'
65
- }
66
- }.each_pair do |server_type, response|
67
- context "with server type #{server_type}" do
68
- let(:command_response) { ERB.new(response[:command]).result(binding) }
69
-
70
- before do
71
- config_response = ERB.new(response[:config]).result(binding)
72
- test_data_xml_template = ERB.new(stubbed_response(response[:keepalive_template_path]))
73
-
74
- allow(SecureRandom).to receive(:uuid).and_return(command_id)
75
- allow(subject).to receive(:command_output_message)
76
- .with(shell_id, command_id)
77
- .and_return(output_message)
78
- allow_any_instance_of(WinRM::WSMV::CreatePipeline).to receive(:build)
79
- .and_return(command_payload)
80
- allow_any_instance_of(WinRM::WSMV::CloseShell).to receive(:build)
81
- .and_return(close_shell_payload)
82
- allow_any_instance_of(WinRM::WSMV::InitRunspacePool).to receive(:build)
83
- .and_return(create_shell_payload)
84
- allow_any_instance_of(WinRM::WSMV::Configuration).to receive(:build)
85
- .and_return(configuration_payload)
86
- allow_any_instance_of(WinRM::WSMV::CleanupCommand).to receive(:build)
87
- .and_return(cleanup_payload)
88
- allow_any_instance_of(WinRM::WSMV::KeepAlive).to receive(:build)
89
- .and_return(keepalive_payload)
90
- allow_any_instance_of(WinRM::PSRP::ReceiveResponseReader).to receive(:read_output)
91
- .with(output_message).and_return(output)
92
- allow(transport).to receive(:send_request).with(configuration_payload) do |_|
93
- # parse real XML with ResponseHandler to raise WinRMSoapFault
94
- WinRM::ResponseHandler.new(config_response, 500).parse_to_xml if server_type == 'omi'
95
- REXML::Document.new(config_response)
96
- end
97
- allow(transport).to receive(:send_request)
98
- .with(create_shell_payload)
99
- .and_return(REXML::Document.new("<blah Name='ShellId'>#{shell_id}</blah>"))
100
- allow(transport).to receive(:send_request)
101
- .with(command_payload)
102
- .and_return(REXML::Document.new(command_response))
103
- allow(transport).to receive(:send_request)
104
- .with(keepalive_payload)
105
- .and_return(REXML::Document.new(test_data_xml_template.result(binding)))
106
- end
107
-
108
- subject { described_class.new(connection_options, transport, Logging.logger['test']) }
109
-
110
- describe '#run' do
111
- it 'opens a shell and gets shell id' do
112
- subject.run(command)
113
- expect(subject.shell_id).to eq shell_id
114
- end
115
-
116
- it 'sends create shell through transport' do
117
- expect(transport).to receive(:send_request).with(create_shell_payload)
118
- subject.run(command)
119
- end
120
-
121
- it 'sends keepalive shell through transport' do
122
- expect(transport).to receive(:send_request).with(keepalive_payload)
123
- subject.run(command)
124
- end
125
-
126
- it 'returns output from generated command' do
127
- expect(subject.run(command)).to eq output
128
- end
129
-
130
- it 'sends command through transport' do
131
- expect(transport).to receive(:send_request).with(command_payload)
132
- subject.run(command)
133
- end
134
-
135
- it 'sends cleanup message through transport' do
136
- expect(transport).to receive(:send_request).with(cleanup_payload)
137
- subject.run(command)
138
- end
139
-
140
- # OMI server doesn't respond to configuration so these tests are irrelevant there
141
- context 'non admin user', if: server_type == 'powershell' do
142
- before do
143
- allow(transport).to receive(:send_request)
144
- .with(configuration_payload)
145
- .and_raise(WinRM::WinRMWSManFault.new('no access for you', '5'))
146
- end
147
-
148
- context 'protocol version 2.1' do
149
- let(:protocol_version) { 2.1 }
150
- let(:command) { 'c' * 200000 }
151
-
152
- it 'sets the fragmenter max_blob_length' do
153
- expect_any_instance_of(WinRM::PSRP::MessageFragmenter).to receive(:max_blob_length=)
154
- .with(153600)
155
- subject.run(command)
156
- end
157
-
158
- it 'fragments messages smaller than max envelope size' do
159
- allow_any_instance_of(WinRM::WSMV::CreatePipeline).to receive(:build)
160
- .and_call_original
161
- allow(transport).to receive(:send_request).with(/CommandLine/) do |payload|
162
- expect(payload.length).to eq 206512
163
- end.and_return(REXML::Document.new(command_response))
164
- subject.run(command)
165
- end
166
- end
167
-
168
- context 'protocol version 2.2' do
169
- let(:protocol_version) { 2.2 }
170
- let(:command) { 'c' * 200000 }
171
-
172
- it 'sets the fragmenter max_blob_length' do
173
- expect_any_instance_of(WinRM::PSRP::MessageFragmenter).to receive(:max_blob_length=)
174
- .with(512000)
175
- subject.run(command)
176
- end
177
-
178
- it 'fragments messages smaller than max envelope size' do
179
- allow_any_instance_of(WinRM::WSMV::CreatePipeline).to receive(:build)
180
- .and_call_original
181
- allow(transport).to receive(:send_request).with(/CommandLine/) do |payload|
182
- expect(payload.length).to eq 276028
183
- end.and_return(REXML::Document.new(command_response))
184
- subject.run(command)
185
- end
186
- end
187
- end
188
-
189
- context 'fragment large command' do
190
- let(:command) { 'c' * 200000 }
191
-
192
- it 'fragments messages as large as max envelope size' do
193
- allow_any_instance_of(WinRM::WSMV::CreatePipeline).to receive(:build).and_call_original
194
- allow(transport).to receive(:send_request).with(/CommandLine/) do |payload|
195
- fallback = subject.max_fragment_blob_size ==
196
- WinRM::PSRP::MessageFragmenter::DEFAULT_BLOB_LENGTH
197
- # OMI server uses default blob size b/c config endpoint unavailable
198
- expect(payload.length).to eq fallback ? 45404 : max_envelope_size_kb * 1024
199
- end.and_return(REXML::Document.new(command_response))
200
- subject.run(command)
201
- end
202
- end
203
- end
204
-
205
- describe '#close' do
206
- it 'sends close shell through transport' do
207
- subject.run(command)
208
- expect(transport).to receive(:send_request).with(close_shell_payload)
209
- subject.close
210
- end
211
-
212
- it 'creates a shell closer with powershell uri' do
213
- allow(WinRM::WSMV::CloseShell).to receive(:new) do |_, opts|
214
- expect(opts[:shell_uri]).to be WinRM::WSMV::Header::RESOURCE_URI_POWERSHELL
215
- end.and_call_original
216
- subject.close
217
- end
218
- end
219
- end
220
- end
221
- end