knife-windows 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -5
  3. data/.travis.yml +20 -20
  4. data/CHANGELOG.md +87 -83
  5. data/DOC_CHANGES.md +20 -20
  6. data/Gemfile +12 -12
  7. data/LICENSE +201 -201
  8. data/README.md +396 -396
  9. data/RELEASE_NOTES.md +34 -34
  10. data/Rakefile +21 -21
  11. data/appveyor.yml +42 -42
  12. data/ci.gemfile +15 -15
  13. data/features/knife_help.feature +20 -20
  14. data/features/support/env.rb +5 -5
  15. data/knife-windows.gemspec +28 -28
  16. data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +247 -247
  17. data/lib/chef/knife/bootstrap_windows_base.rb +407 -401
  18. data/lib/chef/knife/bootstrap_windows_ssh.rb +110 -110
  19. data/lib/chef/knife/bootstrap_windows_winrm.rb +95 -102
  20. data/lib/chef/knife/core/windows_bootstrap_context.rb +362 -362
  21. data/lib/chef/knife/knife_windows_base.rb +33 -33
  22. data/lib/chef/knife/windows_cert_generate.rb +155 -155
  23. data/lib/chef/knife/windows_cert_install.rb +68 -68
  24. data/lib/chef/knife/windows_helper.rb +36 -36
  25. data/lib/chef/knife/windows_listener_create.rb +107 -107
  26. data/lib/chef/knife/winrm.rb +122 -212
  27. data/lib/chef/knife/winrm_base.rb +118 -118
  28. data/lib/chef/knife/winrm_knife_base.rb +309 -218
  29. data/lib/chef/knife/winrm_session.rb +82 -82
  30. data/lib/chef/knife/winrm_shared_options.rb +47 -47
  31. data/lib/chef/knife/wsman_endpoint.rb +44 -44
  32. data/lib/chef/knife/wsman_test.rb +95 -95
  33. data/lib/knife-windows/path_helper.rb +234 -234
  34. data/lib/knife-windows/version.rb +6 -6
  35. data/spec/assets/win_template_rendered_with_bootstrap_install_command.txt +217 -217
  36. data/spec/assets/win_template_rendered_with_bootstrap_install_command_on_12_5_client.txt +217 -217
  37. data/spec/assets/win_template_rendered_without_bootstrap_install_command.txt +329 -329
  38. data/spec/assets/win_template_rendered_without_bootstrap_install_command_on_12_5_client.txt +329 -329
  39. data/spec/assets/win_template_unrendered.txt +246 -246
  40. data/spec/functional/bootstrap_download_spec.rb +234 -233
  41. data/spec/spec_helper.rb +88 -88
  42. data/spec/unit/knife/bootstrap_options_spec.rb +148 -146
  43. data/spec/unit/knife/bootstrap_template_spec.rb +92 -92
  44. data/spec/unit/knife/bootstrap_windows_winrm_spec.rb +259 -243
  45. data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +151 -151
  46. data/spec/unit/knife/windows_cert_generate_spec.rb +90 -90
  47. data/spec/unit/knife/windows_cert_install_spec.rb +51 -51
  48. data/spec/unit/knife/windows_listener_create_spec.rb +76 -76
  49. data/spec/unit/knife/winrm_session_spec.rb +73 -73
  50. data/spec/unit/knife/winrm_spec.rb +551 -504
  51. data/spec/unit/knife/wsman_test_spec.rb +178 -175
  52. metadata +3 -23
@@ -1,51 +1,51 @@
1
- #
2
- # Author:: Mukta Aphale <mukta.aphale@clogeny.com>
3
- # Copyright:: Copyright (c) 2014 Opscode, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'spec_helper'
20
- require 'chef/knife/windows_cert_install'
21
-
22
- describe Chef::Knife::WindowsCertInstall do
23
- context "on Windows" do
24
- before do
25
- allow(Chef::Platform).to receive(:windows?).and_return(true)
26
- @certinstall = Chef::Knife::WindowsCertInstall.new
27
- end
28
-
29
- it "installs certificate" do
30
- @certinstall.name_args = ["test-path"]
31
- @certinstall.config[:cert_passphrase] = "your-secret!"
32
- allow(Chef::Platform).to receive(:windows?).and_return(true)
33
- expect(@certinstall).to receive(:`).with("powershell.exe -Command \" 'your-secret!' | certutil -importPFX 'test-path' AT_KEYEXCHANGE\"")
34
- expect(@certinstall.ui).to receive(:info).with("Certificate added to Certificate Store")
35
- expect(@certinstall.ui).to receive(:info).with("Adding certificate to the Windows Certificate Store...")
36
- @certinstall.run
37
- end
38
- end
39
-
40
- context "not on Windows" do
41
- before do
42
- allow(Chef::Platform).to receive(:windows?).and_return(false)
43
- @listener = Chef::Knife::WindowsListenerCreate.new
44
- end
45
-
46
- it "exits with an error" do
47
- expect(@listener.ui).to receive(:error)
48
- expect { @listener.run }.to raise_error(SystemExit)
49
- end
50
- end
51
- end
1
+ #
2
+ # Author:: Mukta Aphale <mukta.aphale@clogeny.com>
3
+ # Copyright:: Copyright (c) 2014 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'spec_helper'
20
+ require 'chef/knife/windows_cert_install'
21
+
22
+ describe Chef::Knife::WindowsCertInstall do
23
+ context "on Windows" do
24
+ before do
25
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
26
+ @certinstall = Chef::Knife::WindowsCertInstall.new
27
+ end
28
+
29
+ it "installs certificate" do
30
+ @certinstall.name_args = ["test-path"]
31
+ @certinstall.config[:cert_passphrase] = "your-secret!"
32
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
33
+ expect(@certinstall).to receive(:`).with("powershell.exe -Command \" 'your-secret!' | certutil -importPFX 'test-path' AT_KEYEXCHANGE\"")
34
+ expect(@certinstall.ui).to receive(:info).with("Certificate added to Certificate Store")
35
+ expect(@certinstall.ui).to receive(:info).with("Adding certificate to the Windows Certificate Store...")
36
+ @certinstall.run
37
+ end
38
+ end
39
+
40
+ context "not on Windows" do
41
+ before do
42
+ allow(Chef::Platform).to receive(:windows?).and_return(false)
43
+ @listener = Chef::Knife::WindowsListenerCreate.new
44
+ end
45
+
46
+ it "exits with an error" do
47
+ expect(@listener.ui).to receive(:error)
48
+ expect { @listener.run }.to raise_error(SystemExit)
49
+ end
50
+ end
51
+ end
@@ -1,76 +1,76 @@
1
- #
2
- # Author:: Mukta Aphale <mukta.aphale@clogeny.com>
3
- # Copyright:: Copyright (c) 2014 Opscode, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'spec_helper'
20
- require 'chef/knife/windows_listener_create'
21
-
22
- describe Chef::Knife::WindowsListenerCreate do
23
- context "on Windows" do
24
- before do
25
- allow(Chef::Platform).to receive(:windows?).and_return(true)
26
- @listener = Chef::Knife::WindowsListenerCreate.new
27
- end
28
-
29
- it "creates winrm listener" do
30
- @listener.config[:hostname] = "host"
31
- @listener.config[:cert_thumbprint] = "CERT-THUMBPRINT"
32
- @listener.config[:port] = "5986"
33
- expect(@listener).to receive(:`).with("winrm create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname=\"host\";CertificateThumbprint=\"CERT-THUMBPRINT\";Port=\"5986\"}")
34
- expect(@listener.ui).to receive(:info).with("WinRM listener created with Port: 5986 and CertificateThumbprint: CERT-THUMBPRINT")
35
- @listener.run
36
- end
37
-
38
- it "raise an error on command failure" do
39
- @listener.config[:hostname] = "host"
40
- @listener.config[:cert_thumbprint] = "CERT-THUMBPRINT"
41
- @listener.config[:port] = "5986"
42
- @listener.config[:basic_auth] = true
43
- expect(@listener).to receive(:`).with("winrm create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname=\"host\";CertificateThumbprint=\"CERT-THUMBPRINT\";Port=\"5986\"}")
44
- expect($?).to receive(:exitstatus).and_return(100)
45
- expect(@listener.ui).to receive(:error).with("Error creating WinRM listener. use -VV for more details.")
46
- expect(@listener.ui).to_not receive(:info).with("WinRM listener created with Port: 5986 and CertificateThumbprint: CERT-THUMBPRINT")
47
- expect { @listener.run }.to raise_error(SystemExit)
48
- end
49
-
50
- it "creates winrm listener with cert install option" do
51
- @listener.config[:hostname] = "host"
52
- @listener.config[:cert_thumbprint] = "CERT-THUMBPRINT"
53
- @listener.config[:port] = "5986"
54
- @listener.config[:cert_install] = true
55
- allow(@listener).to receive(:get_cert_passphrase).and_return("your-secret!")
56
- expect(@listener).to receive(:`).with("powershell.exe -Command \" 'your-secret!' | certutil -importPFX 'true' AT_KEYEXCHANGE\"")
57
- expect(@listener).to receive(:`).with("powershell.exe -Command \" echo (Get-PfxCertificate true).thumbprint \"")
58
- expect(@listener.ui).to receive(:info).with("Certificate installed to Certificate Store")
59
- expect(@listener.ui).to receive(:info).with("Certificate Thumbprint: ")
60
- allow(@listener).to receive(:puts)
61
- @listener.run
62
- end
63
- end
64
-
65
- context "not on Windows" do
66
- before do
67
- allow(Chef::Platform).to receive(:windows?).and_return(false)
68
- @listener = Chef::Knife::WindowsListenerCreate.new
69
- end
70
-
71
- it "exits with an error" do
72
- expect(@listener.ui).to receive(:error)
73
- expect { @listener.run }.to raise_error(SystemExit)
74
- end
75
- end
76
- end
1
+ #
2
+ # Author:: Mukta Aphale <mukta.aphale@clogeny.com>
3
+ # Copyright:: Copyright (c) 2014 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'spec_helper'
20
+ require 'chef/knife/windows_listener_create'
21
+
22
+ describe Chef::Knife::WindowsListenerCreate do
23
+ context "on Windows" do
24
+ before do
25
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
26
+ @listener = Chef::Knife::WindowsListenerCreate.new
27
+ end
28
+
29
+ it "creates winrm listener" do
30
+ @listener.config[:hostname] = "host"
31
+ @listener.config[:cert_thumbprint] = "CERT-THUMBPRINT"
32
+ @listener.config[:port] = "5986"
33
+ expect(@listener).to receive(:`).with("winrm create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname=\"host\";CertificateThumbprint=\"CERT-THUMBPRINT\";Port=\"5986\"}")
34
+ expect(@listener.ui).to receive(:info).with("WinRM listener created with Port: 5986 and CertificateThumbprint: CERT-THUMBPRINT")
35
+ @listener.run
36
+ end
37
+
38
+ it "raise an error on command failure" do
39
+ @listener.config[:hostname] = "host"
40
+ @listener.config[:cert_thumbprint] = "CERT-THUMBPRINT"
41
+ @listener.config[:port] = "5986"
42
+ @listener.config[:basic_auth] = true
43
+ expect(@listener).to receive(:`).with("winrm create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname=\"host\";CertificateThumbprint=\"CERT-THUMBPRINT\";Port=\"5986\"}")
44
+ expect($?).to receive(:exitstatus).and_return(100)
45
+ expect(@listener.ui).to receive(:error).with("Error creating WinRM listener. use -VV for more details.")
46
+ expect(@listener.ui).to_not receive(:info).with("WinRM listener created with Port: 5986 and CertificateThumbprint: CERT-THUMBPRINT")
47
+ expect { @listener.run }.to raise_error(SystemExit)
48
+ end
49
+
50
+ it "creates winrm listener with cert install option" do
51
+ @listener.config[:hostname] = "host"
52
+ @listener.config[:cert_thumbprint] = "CERT-THUMBPRINT"
53
+ @listener.config[:port] = "5986"
54
+ @listener.config[:cert_install] = true
55
+ allow(@listener).to receive(:get_cert_passphrase).and_return("your-secret!")
56
+ expect(@listener).to receive(:`).with("powershell.exe -Command \" 'your-secret!' | certutil -importPFX 'true' AT_KEYEXCHANGE\"")
57
+ expect(@listener).to receive(:`).with("powershell.exe -Command \" echo (Get-PfxCertificate true).thumbprint \"")
58
+ expect(@listener.ui).to receive(:info).with("Certificate installed to Certificate Store")
59
+ expect(@listener.ui).to receive(:info).with("Certificate Thumbprint: ")
60
+ allow(@listener).to receive(:puts)
61
+ @listener.run
62
+ end
63
+ end
64
+
65
+ context "not on Windows" do
66
+ before do
67
+ allow(Chef::Platform).to receive(:windows?).and_return(false)
68
+ @listener = Chef::Knife::WindowsListenerCreate.new
69
+ end
70
+
71
+ it "exits with an error" do
72
+ expect(@listener.ui).to receive(:error)
73
+ expect { @listener.run }.to raise_error(SystemExit)
74
+ end
75
+ end
76
+ end
@@ -1,74 +1,74 @@
1
- #
2
- # Author:: Steven Murawski <smurawski@chef.io>
3
- # Copyright:: Copyright (c) 2015 Opscode, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'spec_helper'
20
-
21
- Chef::Knife::Winrm.load_deps
22
-
23
-
24
- describe Chef::Knife::WinrmSession do
25
- let(:winrm_service) { double('WinRMWebService') }
26
- let(:options) { { transport: :plaintext } }
27
-
28
- before do
29
- @original_config = Chef::Config.hash_dup
30
- allow(WinRM::WinRMWebService).to receive(:new).and_return(winrm_service)
31
- allow(winrm_service).to receive(:set_timeout)
32
- end
33
-
34
- after do
35
- Chef::Config.configuration = @original_config
36
- end
37
-
38
- subject { Chef::Knife::WinrmSession.new(options) }
39
-
40
- describe "#initialize" do
41
- context "when using sspinegotiate transport" do
42
- let(:options) { { transport: :sspinegotiate } }
43
-
44
- it "uses winrm-s" do
45
- expect(Chef::Knife::WinrmSession).to receive(:load_windows_specific_gems)
46
- subject
47
- end
48
- end
49
-
50
- context "when a proxy is configured" do
51
- let(:proxy_uri) { 'blah.com' }
52
-
53
- before do
54
- Chef::Config[:http_proxy] = proxy_uri
55
- end
56
-
57
- it "sets the http_proxy to the configured proxy" do
58
- subject
59
- expect(ENV['HTTP_PROXY']).to eq("http://#{proxy_uri}")
60
- end
61
- end
62
- end
63
-
64
- describe "#relay_command" do
65
- it "run command and display commands output" do
66
- expect(winrm_service).to receive(:open_shell).ordered
67
- expect(winrm_service).to receive(:run_command).ordered
68
- expect(winrm_service).to receive(:get_command_output).ordered.and_return({})
69
- expect(winrm_service).to receive(:cleanup_command).ordered
70
- expect(winrm_service).to receive(:close_shell).ordered
71
- subject.relay_command("cmd.exe echo 'hi'")
72
- end
73
- end
1
+ #
2
+ # Author:: Steven Murawski <smurawski@chef.io>
3
+ # Copyright:: Copyright (c) 2015 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'spec_helper'
20
+
21
+ Chef::Knife::Winrm.load_deps
22
+
23
+
24
+ describe Chef::Knife::WinrmSession do
25
+ let(:winrm_service) { double('WinRMWebService') }
26
+ let(:options) { { transport: :plaintext } }
27
+
28
+ before do
29
+ @original_config = Chef::Config.hash_dup
30
+ allow(WinRM::WinRMWebService).to receive(:new).and_return(winrm_service)
31
+ allow(winrm_service).to receive(:set_timeout)
32
+ end
33
+
34
+ after do
35
+ Chef::Config.configuration = @original_config
36
+ end
37
+
38
+ subject { Chef::Knife::WinrmSession.new(options) }
39
+
40
+ describe "#initialize" do
41
+ context "when using sspinegotiate transport" do
42
+ let(:options) { { transport: :sspinegotiate } }
43
+
44
+ it "uses winrm-s" do
45
+ expect(Chef::Knife::WinrmSession).to receive(:load_windows_specific_gems)
46
+ subject
47
+ end
48
+ end
49
+
50
+ context "when a proxy is configured" do
51
+ let(:proxy_uri) { 'blah.com' }
52
+
53
+ before do
54
+ Chef::Config[:http_proxy] = proxy_uri
55
+ end
56
+
57
+ it "sets the http_proxy to the configured proxy" do
58
+ subject
59
+ expect(ENV['HTTP_PROXY']).to eq("http://#{proxy_uri}")
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#relay_command" do
65
+ it "run command and display commands output" do
66
+ expect(winrm_service).to receive(:open_shell).ordered
67
+ expect(winrm_service).to receive(:run_command).ordered
68
+ expect(winrm_service).to receive(:get_command_output).ordered.and_return({})
69
+ expect(winrm_service).to receive(:cleanup_command).ordered
70
+ expect(winrm_service).to receive(:close_shell).ordered
71
+ subject.relay_command("cmd.exe echo 'hi'")
72
+ end
73
+ end
74
74
  end
@@ -1,504 +1,551 @@
1
- #
2
- # Author:: Bryan McLellan <btm@opscode.com>
3
- # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'spec_helper'
20
-
21
- Chef::Knife::Winrm.load_deps
22
-
23
- describe Chef::Knife::Winrm do
24
- before(:all) do
25
- @original_config = Chef::Config.hash_dup
26
- @original_knife_config = Chef::Config[:knife].nil? ? nil : Chef::Config[:knife].dup
27
- end
28
-
29
- after do
30
- Chef::Config.configuration = @original_config
31
- Chef::Config[:knife] = @original_knife_config if @original_knife_config
32
- end
33
-
34
- describe "#resolve_target_nodes" do
35
- before do
36
- @knife = Chef::Knife::Winrm.new
37
- @knife.config[:attribute] = "fqdn"
38
- @node_foo = Chef::Node.new
39
- @node_foo.automatic_attrs[:fqdn] = "foo.example.org"
40
- @node_foo.automatic_attrs[:ipaddress] = "10.0.0.1"
41
- @node_bar = Chef::Node.new
42
- @node_bar.automatic_attrs[:fqdn] = "bar.example.org"
43
- @node_bar.automatic_attrs[:ipaddress] = "10.0.0.2"
44
- @node_bar.automatic_attrs[:ec2][:public_hostname] = "somewhere.com"
45
- @query = double("Chef::Search::Query")
46
- end
47
-
48
- context "when there are some hosts found but they do not have an attribute to connect with" do
49
- before do
50
- @knife.config[:manual] = false
51
- @knife.config[:winrm_password] = 'P@ssw0rd!'
52
- allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
53
- @node_foo.automatic_attrs[:fqdn] = nil
54
- @node_bar.automatic_attrs[:fqdn] = nil
55
- allow(Chef::Search::Query).to receive(:new).and_return(@query)
56
- end
57
-
58
- it "raises a specific error (KNIFE-222)" do
59
- expect(@knife.ui).to receive(:fatal).with(/does not have the required attribute/)
60
- expect(@knife).to receive(:exit).with(10)
61
- @knife.configure_chef
62
- @knife.resolve_target_nodes
63
- end
64
- end
65
-
66
- context "when there are nested attributes" do
67
- before do
68
- @knife.config[:manual] = false
69
- @knife.config[:winrm_password] = 'P@ssw0rd!'
70
- allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
71
- allow(Chef::Search::Query).to receive(:new).and_return(@query)
72
- end
73
-
74
- it "uses the nested attributes (KNIFE-276)" do
75
- @knife.config[:attribute] = "ec2.public_hostname"
76
- @knife.configure_chef
77
- @knife.resolve_target_nodes
78
- end
79
- end
80
- end
81
-
82
- describe "#configure_session" do
83
- let(:winrm_user) { 'testuser' }
84
- let(:transport) { 'plaintext' }
85
- let(:protocol) { 'basic' }
86
- let(:knife_args) do
87
- [
88
- '-m', 'localhost',
89
- '-x', winrm_user,
90
- '-P', 'testpassword',
91
- '-t', transport,
92
- '--winrm-authentication-protocol', protocol,
93
- 'echo helloworld'
94
- ]
95
- end
96
- let(:winrm_session) { double('winrm_session') }
97
- let(:winrm_service) { double('WinRMWebService') }
98
-
99
- before do
100
- allow(winrm_service).to receive(:set_timeout)
101
- end
102
-
103
- subject { Chef::Knife::Winrm.new(knife_args) }
104
-
105
- context "when configuring the WinRM user name" do
106
- context "when basic auth is used" do
107
- let(:protocol) { 'basic' }
108
-
109
- it "passes user name as given in options" do
110
- expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
111
- expect(opts[:user]).to eq(winrm_user)
112
- end.and_return(winrm_session)
113
- subject.configure_session
114
- end
115
- end
116
-
117
- context "when negotiate auth is used" do
118
- let(:protocol) { 'negotiate' }
119
-
120
- context "when user is prefixed with realm" do
121
- let(:winrm_user) { "my_realm\\myself" }
122
-
123
- it "passes user name as given in options" do
124
- expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
125
- expect(opts[:user]).to eq(winrm_user)
126
- end.and_return(winrm_session)
127
- subject.configure_session
128
- end
129
- end
130
-
131
- context "when user realm is included via email format" do
132
- let(:winrm_user) { "myself@my_realm.com" }
133
-
134
- it "passes user name as given in options" do
135
- expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
136
- expect(opts[:user]).to eq(winrm_user)
137
- end.and_return(winrm_session)
138
- subject.configure_session
139
- end
140
- end
141
-
142
- context "when a local user is given" do
143
- it "prefixes user with the dot (local) realm" do
144
- expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
145
- expect(opts[:user]).to eq(".\\#{winrm_user}")
146
- end.and_return(winrm_session)
147
- subject.configure_session
148
- end
149
- end
150
- end
151
- end
152
-
153
- context "when configuring the WinRM transport" do
154
- before(:all) do
155
- @winrm_session = Object.new
156
- @winrm_session.define_singleton_method(:set_timeout){|timeout| ""}
157
- end
158
-
159
- context "kerberos option is set" do
160
- let(:winrm_command_http) { Chef::Knife::Winrm.new([
161
- '-m', 'localhost',
162
- '-x', 'testuser',
163
- '-P', 'testpassword',
164
- '--winrm-authentication-protocol', 'basic',
165
- '--kerberos-realm', 'realm',
166
- 'echo helloworld'
167
- ]) }
168
-
169
- it "sets the transport to kerberos" do
170
- expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5985/wsman', :kerberos, anything).and_return(@winrm_session)
171
- winrm_command_http.configure_chef
172
- winrm_command_http.configure_session
173
- end
174
- end
175
-
176
- context "kerberos option is set but nil" do
177
- let(:winrm_command_http) { Chef::Knife::Winrm.new([
178
- '-m', 'localhost',
179
- '-x', 'testuser',
180
- '-P', 'testpassword',
181
- '--winrm-authentication-protocol', 'basic',
182
- 'echo helloworld'
183
- ]) }
184
-
185
- it "sets the transport to plaintext" do
186
- winrm_command_http.config[:kerberos_realm] = nil
187
- expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5985/wsman', :plaintext, anything).and_return(@winrm_session)
188
- winrm_command_http.configure_chef
189
- winrm_command_http.configure_session
190
- end
191
- end
192
-
193
- context "on windows workstations" do
194
- let(:protocol) { 'negotiate' }
195
-
196
- before do
197
- allow(Chef::Platform).to receive(:windows?).and_return(true)
198
- end
199
-
200
- it "defaults to negotiate when on a Windows host" do
201
- expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
202
- expect(opts[:transport]).to eq(:sspinegotiate)
203
- end.and_return(winrm_session)
204
- subject.configure_session
205
- end
206
- end
207
-
208
- context "on non-windows workstations" do
209
- before do
210
- allow(Chef::Platform).to receive(:windows?).and_return(false)
211
- end
212
-
213
- let(:winrm_command_http) { Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '-t', 'plaintext', '--winrm-authentication-protocol', 'basic', 'echo helloworld']) }
214
-
215
- it "defaults to the http uri scheme" do
216
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :plaintext)).and_call_original
217
- expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5985/wsman', anything, anything).and_return(@winrm_session)
218
- winrm_command_http.configure_chef
219
- winrm_command_http.configure_session
220
- end
221
-
222
- it "sets the operation timeout and verifes default" do
223
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :plaintext)).and_call_original
224
- expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5985/wsman', anything, anything).and_return(@winrm_session)
225
- expect(@winrm_session).to receive(:set_timeout).with(1800)
226
- winrm_command_http.configure_chef
227
- winrm_command_http.configure_session
228
- end
229
-
230
- it "sets the user specified winrm port" do
231
- Chef::Config[:knife] = {winrm_port: "5988"}
232
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :plaintext)).and_call_original
233
- expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5988/wsman', anything, anything).and_return(@winrm_session)
234
- winrm_command_http.configure_chef
235
- winrm_command_http.configure_session
236
- end
237
-
238
- let(:winrm_command_timeout) { Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '--winrm-authentication-protocol', 'basic', '--session-timeout', '10', 'echo helloworld']) }
239
-
240
- it "sets operation timeout and verify 10 Minute timeout" do
241
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :plaintext)).and_call_original
242
- expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5985/wsman', anything, anything).and_return(@winrm_session)
243
- expect(@winrm_session).to receive(:set_timeout).with(600)
244
- winrm_command_timeout.configure_chef
245
- winrm_command_timeout.configure_session
246
- end
247
-
248
- let(:winrm_command_https) { Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '--winrm-transport', 'ssl', 'echo helloworld']) }
249
-
250
- it "uses the https uri scheme if the ssl transport is specified" do
251
- Chef::Config[:knife] = {:winrm_transport => 'ssl'}
252
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
253
- expect(WinRM::WinRMWebService).to receive(:new).with('https://localhost:5986/wsman', anything, anything).and_return(@winrm_session)
254
- winrm_command_https.configure_chef
255
- winrm_command_https.configure_session
256
- end
257
-
258
- it "uses the winrm port '5986' by default for ssl transport" do
259
- Chef::Config[:knife] = {:winrm_transport => 'ssl'}
260
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
261
- expect(WinRM::WinRMWebService).to receive(:new).with('https://localhost:5986/wsman', anything, anything).and_return(@winrm_session)
262
- winrm_command_https.configure_chef
263
- winrm_command_https.configure_session
264
- end
265
-
266
- it "defaults to validating the server when the ssl transport is used" do
267
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
268
- expect(WinRM::WinRMWebService).to receive(:new).with(anything, anything, hash_including(:no_ssl_peer_verification => false)).and_return(@winrm_session)
269
- winrm_command_https.configure_chef
270
- winrm_command_https.configure_session
271
- end
272
-
273
- let(:winrm_command_verify_peer) { Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '--winrm-transport', 'ssl', '--winrm-ssl-verify-mode', 'verify_peer', 'echo helloworld'])}
274
-
275
- it "validates the server when the ssl transport is used and the :winrm_ssl_verify_mode option is not configured to :verify_none" do
276
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
277
- expect(WinRM::WinRMWebService).to receive(:new).with(anything, anything, hash_including(:no_ssl_peer_verification => false)).and_return(@winrm_session)
278
- winrm_command_verify_peer.configure_chef
279
- winrm_command_verify_peer.configure_session
280
- end
281
-
282
- context "when setting verify_none" do
283
- let(:transport) { 'ssl' }
284
-
285
- before { knife_args << '--winrm-ssl-verify-mode' << 'verify_none' }
286
-
287
- it "does not validate the server when the ssl transport is used and the :winrm_ssl_verify_mode option is set to :verify_none" do
288
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
289
- expect(WinRM::WinRMWebService).to receive(:new).with(anything, anything, hash_including(:no_ssl_peer_verification => true)).and_return(@winrm_session)
290
- subject.configure_chef
291
- subject.configure_session
292
- end
293
-
294
- it "prints warning output when the :winrm_ssl_verify_mode set to :verify_none to disable server validation" do
295
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
296
- expect(WinRM::WinRMWebService).to receive(:new).with(anything, anything, hash_including(:no_ssl_peer_verification => true)).and_return(@winrm_session)
297
- expect(subject).to receive(:warn_no_ssl_peer_verification)
298
-
299
- subject.configure_chef
300
- subject.configure_session
301
- end
302
-
303
- context "when transport is plaintext" do
304
- let(:transport) { 'plaintext' }
305
-
306
- it "does not print warning re ssl server validation" do
307
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :plaintext)).and_call_original
308
- expect(WinRM::WinRMWebService).to receive(:new).and_return(winrm_service)
309
- expect(subject).to_not receive(:warn_no_ssl_peer_verification)
310
-
311
- subject.configure_chef
312
- subject.configure_session
313
- end
314
- end
315
- end
316
-
317
- let(:winrm_command_ca_trust) { Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '--winrm-transport', 'ssl', '--ca-trust-file', '~/catrustroot', '--winrm-ssl-verify-mode', 'verify_none', 'echo helloworld'])}
318
-
319
- it "validates the server when the ssl transport is used and the :ca_trust_file option is specified even if the :winrm_ssl_verify_mode option is set to :verify_none" do
320
- expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
321
- expect(WinRM::WinRMWebService).to receive(:new).with(anything, anything, hash_including(:no_ssl_peer_verification => false)).and_return(@winrm_session)
322
- winrm_command_ca_trust.configure_chef
323
- winrm_command_ca_trust.configure_session
324
- end
325
- end
326
- end
327
- end
328
-
329
- describe "#run" do
330
- before(:each) do
331
- Chef::Config[:knife] = {:winrm_transport => 'plaintext'}
332
- @winrm = Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '--winrm-authentication-protocol', 'basic', 'echo helloworld'])
333
- end
334
-
335
- it "returns with 0 if the command succeeds" do
336
- allow(@winrm).to receive(:relay_winrm_command).and_return(0)
337
- return_code = @winrm.run
338
- expect(return_code).to be_zero
339
- end
340
-
341
- it "exits with exact exit status if the command fails and returns config is set to 0" do
342
- command_status = 510
343
- session_mock = Chef::Knife::WinrmSession.new({:transport => :plaintext, :host => 'localhost', :port => '5985'})
344
-
345
- @winrm.config[:returns] = "0"
346
- Chef::Config[:knife][:returns] = [0]
347
-
348
- allow(@winrm).to receive(:relay_winrm_command)
349
- allow(@winrm.ui).to receive(:error)
350
- allow(Chef::Knife::WinrmSession).to receive(:new).and_return(session_mock)
351
- allow(session_mock).to receive(:exit_code).and_return(command_status)
352
- expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(command_status) }
353
- end
354
-
355
- it "exits with non-zero status if the command fails and returns config is set to 0" do
356
- command_status = 1
357
- @winrm.config[:returns] = "0,53"
358
- Chef::Config[:knife][:returns] = [0,53]
359
- allow(@winrm).to receive(:relay_winrm_command).and_return(command_status)
360
- allow(@winrm.ui).to receive(:error)
361
- session_mock = Chef::Knife::WinrmSession.new({:transport => :plaintext, :host => 'localhost', :port => '5985'})
362
- allow(Chef::Knife::WinrmSession).to receive(:new).and_return(session_mock)
363
- allow(session_mock).to receive(:exit_code).and_return(command_status)
364
- expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(command_status) }
365
- end
366
-
367
- it "exits with a zero status if the command returns an expected non-zero status" do
368
- command_status = 53
369
- Chef::Config[:knife][:returns] = [0,53]
370
- allow(@winrm).to receive(:relay_winrm_command).and_return(command_status)
371
- session_mock = Chef::Knife::WinrmSession.new({:transport => :plaintext, :host => 'localhost', :port => '5985'})
372
- allow(Chef::Knife::WinrmSession).to receive(:new).and_return(session_mock)
373
- allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
374
- exit_code = @winrm.run
375
- expect(exit_code).to be_zero
376
- end
377
-
378
- it "exits with a zero status if the command returns an expected non-zero status" do
379
- command_status = 53
380
- @winrm.config[:returns] = '0,53'
381
- allow(@winrm).to receive(:relay_winrm_command).and_return(command_status)
382
- session_mock = Chef::Knife::WinrmSession.new({:transport => :plaintext, :host => 'localhost', :port => '5985'})
383
- allow(Chef::Knife::WinrmSession).to receive(:new).and_return(session_mock)
384
- allow(session_mock).to receive(:exit_codes).and_return({"thishost" => command_status})
385
- exit_code = @winrm.run
386
- expect(exit_code).to be_zero
387
- end
388
-
389
- it "exits with 100 and no hint if command execution raises an exception other than 401" do
390
- allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('', '500'))
391
- allow(@winrm.ui).to receive(:error)
392
- expect(@winrm.ui).to_not receive(:info)
393
- expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(100) }
394
- end
395
-
396
- it "exits with 100 if command execution raises a 401" do
397
- allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('', '401'))
398
- allow(@winrm.ui).to receive(:info)
399
- allow(@winrm.ui).to receive(:error)
400
- expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(100) }
401
- end
402
-
403
- it "exits with 0 if command execution raises a 401 and suppress_auth_failure is set to true" do
404
- @winrm.config[:suppress_auth_failure] = true
405
- allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('', '401'))
406
- exit_code = @winrm.run_with_pretty_exceptions
407
- expect(exit_code).to eq(401)
408
- end
409
-
410
- it "prints a hint on failure for negotiate authentication" do
411
- @winrm.config[:winrm_authentication_protocol] = "negotiate"
412
- @winrm.config[:winrm_transport] = "plaintext"
413
- allow(Chef::Platform).to receive(:windows?).and_return(true)
414
- allow(Chef::Knife::WinrmSession).to receive(:new)
415
- allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMAuthorizationError.new)
416
- allow(@winrm.ui).to receive(:error)
417
- allow(@winrm.ui).to receive(:info)
418
- expect(@winrm.ui).to receive(:info).with(Chef::Knife::Winrm::FAILED_NOT_BASIC_HINT)
419
- expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit)
420
- end
421
-
422
- it "prints a hint on failure for basic authentication" do
423
- @winrm.config[:winrm_authentication_protocol] = "basic"
424
- @winrm.config[:winrm_transport] = "plaintext"
425
- allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('', '401'))
426
- allow(@winrm.ui).to receive(:error)
427
- allow(@winrm.ui).to receive(:info)
428
- expect(@winrm.ui).to receive(:info).with(Chef::Knife::Winrm::FAILED_BASIC_HINT)
429
- expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit)
430
- end
431
-
432
- context "when winrm_authentication_protocol specified" do
433
- before do
434
- Chef::Config[:knife] = {:winrm_transport => 'plaintext'}
435
- allow(@winrm).to receive(:relay_winrm_command).and_return(0)
436
- end
437
-
438
- it "sets sspinegotiate transport on windows for 'negotiate' authentication" do
439
- @winrm.config[:winrm_authentication_protocol] = "negotiate"
440
- allow(Chef::Platform).to receive(:windows?).and_return(true)
441
- expect(@winrm).to receive(:create_winrm_session).with({:user=>".\\testuser", :password=>"testpassword", :port=>"5985", :no_ssl_peer_verification => false, :basic_auth_only=>false, :operation_timeout=>1800, :transport=>:sspinegotiate, :disable_sspi=>false, :host=>"localhost"})
442
- exit_code = @winrm.run
443
- end
444
-
445
- it "does not have winrm opts transport set to sspinegotiate for unix" do
446
- @winrm.config[:winrm_authentication_protocol] = "negotiate"
447
- allow(Chef::Platform).to receive(:windows?).and_return(false)
448
- allow(@winrm).to receive(:exit)
449
- expect(@winrm).to receive(:create_winrm_session).with({:user=>".\\testuser", :password=>"testpassword", :port=>"5985", :no_ssl_peer_verification=>false, :basic_auth_only=>false, :operation_timeout=>1800, :transport=>:plaintext, :disable_sspi=>true, :host=>"localhost"})
450
- exit_code = @winrm.run
451
- end
452
-
453
- it "applies winrm monkey patch on windows if 'negotiate' authentication and 'plaintext' transport is specified", :windows_only => true do
454
- @winrm.config[:winrm_authentication_protocol] = "negotiate"
455
- allow(Chef::Platform).to receive(:windows?).and_return(true)
456
- allow(@winrm.ui).to receive(:warn)
457
- @winrm.run
458
- end
459
-
460
- it "raises an error if value is other than [basic, negotiate, kerberos]" do
461
- @winrm.config[:winrm_authentication_protocol] = "invalid"
462
- allow(Chef::Platform).to receive(:windows?).and_return(true)
463
- expect(@winrm.ui).to receive(:error)
464
- expect { @winrm.run }.to raise_error(SystemExit)
465
- end
466
-
467
- it "skips the winrm monkey patch for 'basic' authentication" do
468
- @winrm.config[:winrm_authentication_protocol] = "basic"
469
- allow(Chef::Platform).to receive(:windows?).and_return(true)
470
- @winrm.run
471
- end
472
-
473
- it "skips the winrm monkey patch for 'kerberos' authentication" do
474
- @winrm.config[:winrm_authentication_protocol] = "kerberos"
475
- allow(Chef::Platform).to receive(:windows?).and_return(true)
476
- @winrm.run
477
- end
478
-
479
- it "skips the winrm monkey patch for 'ssl' transport and 'negotiate' authentication" do
480
- @winrm.config[:winrm_authentication_protocol] = "negotiate"
481
- @winrm.config[:winrm_transport] = "ssl"
482
- allow(Chef::Platform).to receive(:windows?).and_return(true)
483
- @winrm.run
484
- end
485
-
486
- it "disables sspi and skips the winrm monkey patch for 'ssl' transport and 'basic' authentication" do
487
- @winrm.config[:winrm_authentication_protocol] = "basic"
488
- @winrm.config[:winrm_transport] = "ssl"
489
- @winrm.config[:winrm_port] = "5986"
490
- allow(Chef::Platform).to receive(:windows?).and_return(true)
491
- expect(@winrm).to receive(:create_winrm_session).with({:user=>"testuser", :password=>"testpassword", :port=>"5986", :no_ssl_peer_verification=>false, :basic_auth_only=>true, :operation_timeout=>1800, :transport=>:ssl, :disable_sspi=>true, :host=>"localhost"})
492
- @winrm.run
493
- end
494
-
495
- it "prints a warning on linux for unencrypted negotiate authentication" do
496
- @winrm.config[:winrm_authentication_protocol] = "negotiate"
497
- @winrm.config[:winrm_transport] = "plaintext"
498
- allow(Chef::Platform).to receive(:windows?).and_return(false)
499
- expect(@winrm.ui).to receive(:warn).once
500
- expect { @winrm.run }.to_not raise_error(SystemExit)
501
- end
502
- end
503
- end
504
- end
1
+ #
2
+ # Author:: Bryan McLellan <btm@opscode.com>
3
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'spec_helper'
20
+
21
+ Chef::Knife::Winrm.load_deps
22
+
23
+ describe Chef::Knife::Winrm do
24
+ before(:all) do
25
+ @original_config = Chef::Config.hash_dup
26
+ @original_knife_config = Chef::Config[:knife].nil? ? nil : Chef::Config[:knife].dup
27
+ end
28
+
29
+ after do
30
+ Chef::Config.configuration = @original_config
31
+ Chef::Config[:knife] = @original_knife_config if @original_knife_config
32
+ end
33
+
34
+ describe "#resolve_target_nodes" do
35
+ before do
36
+ @knife = Chef::Knife::Winrm.new
37
+ @knife.config[:attribute] = "fqdn"
38
+ @node_foo = Chef::Node.new
39
+ @node_foo.automatic_attrs[:fqdn] = "foo.example.org"
40
+ @node_foo.automatic_attrs[:ipaddress] = "10.0.0.1"
41
+ @node_bar = Chef::Node.new
42
+ @node_bar.automatic_attrs[:fqdn] = "bar.example.org"
43
+ @node_bar.automatic_attrs[:ipaddress] = "10.0.0.2"
44
+ @node_bar.automatic_attrs[:ec2][:public_hostname] = "somewhere.com"
45
+ @query = double("Chef::Search::Query")
46
+ end
47
+
48
+ context "when there are some hosts found but they do not have an attribute to connect with" do
49
+ before do
50
+ @knife.config[:manual] = false
51
+ @knife.config[:winrm_password] = 'P@ssw0rd!'
52
+ allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
53
+ @node_foo.automatic_attrs[:fqdn] = nil
54
+ @node_bar.automatic_attrs[:fqdn] = nil
55
+ allow(Chef::Search::Query).to receive(:new).and_return(@query)
56
+ end
57
+
58
+ it "raises a specific error (KNIFE-222)" do
59
+ expect(@knife.ui).to receive(:fatal).with(/does not have the required attribute/)
60
+ expect(@knife).to receive(:exit).with(10)
61
+ @knife.configure_chef
62
+ @knife.resolve_target_nodes
63
+ end
64
+ end
65
+
66
+ context "when there are nested attributes" do
67
+ before do
68
+ @knife.config[:manual] = false
69
+ @knife.config[:winrm_password] = 'P@ssw0rd!'
70
+ allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
71
+ allow(Chef::Search::Query).to receive(:new).and_return(@query)
72
+ end
73
+
74
+ it "uses the nested attributes (KNIFE-276)" do
75
+ @knife.config[:attribute] = "ec2.public_hostname"
76
+ @knife.configure_chef
77
+ @knife.resolve_target_nodes
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "#configure_session" do
83
+ let(:winrm_user) { 'testuser' }
84
+ let(:transport) { 'plaintext' }
85
+ let(:password) { 'testpassword' }
86
+ let(:protocol) { 'basic' }
87
+ let(:knife_args) do
88
+ [
89
+ '-m', 'localhost',
90
+ '-x', winrm_user,
91
+ '-P', password,
92
+ '-t', transport,
93
+ '--winrm-authentication-protocol', protocol,
94
+ 'echo helloworld'
95
+ ]
96
+ end
97
+ let(:winrm_session) { double('winrm_session') }
98
+ let(:winrm_service) { double('WinRMWebService') }
99
+
100
+ before do
101
+ allow(winrm_service).to receive(:set_timeout)
102
+ end
103
+
104
+ subject { Chef::Knife::Winrm.new(knife_args) }
105
+
106
+ context "when configuring the WinRM user name" do
107
+ context "when basic auth is used" do
108
+ let(:protocol) { 'basic' }
109
+
110
+ it "passes user name as given in options" do
111
+ expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
112
+ expect(opts[:user]).to eq(winrm_user)
113
+ end.and_return(winrm_session)
114
+ subject.configure_session
115
+ end
116
+ end
117
+
118
+ context "when negotiate auth is used" do
119
+ let(:protocol) { 'negotiate' }
120
+
121
+ context "when user is prefixed with realm" do
122
+ let(:winrm_user) { "my_realm\\myself" }
123
+
124
+ it "passes user name as given in options" do
125
+ expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
126
+ expect(opts[:user]).to eq(winrm_user)
127
+ end.and_return(winrm_session)
128
+ subject.configure_session
129
+ end
130
+ end
131
+
132
+ context "when user realm is included via email format" do
133
+ let(:winrm_user) { "myself@my_realm.com" }
134
+
135
+ it "passes user name as given in options" do
136
+ expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
137
+ expect(opts[:user]).to eq(winrm_user)
138
+ end.and_return(winrm_session)
139
+ subject.configure_session
140
+ end
141
+ end
142
+
143
+ context "when a local user is given" do
144
+ it "prefixes user with the dot (local) realm" do
145
+ expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
146
+ expect(opts[:user]).to eq(".\\#{winrm_user}")
147
+ end.and_return(winrm_session)
148
+ subject.configure_session
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ context "when configuring the WinRM password" do
155
+ it "passes password as given in options" do
156
+ expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
157
+ expect(opts[:password]).to eq(password)
158
+ end.and_return(winrm_session)
159
+ subject.configure_session
160
+ end
161
+
162
+ context "when no password is given in the options" do
163
+ let(:knife_args) do
164
+ [
165
+ '-m', 'localhost',
166
+ '-x', winrm_user,
167
+ '-t', transport,
168
+ '--winrm-authentication-protocol', protocol,
169
+ 'echo helloworld'
170
+ ]
171
+ end
172
+ let(:prompted_password) { 'prompted_password' }
173
+
174
+ before do
175
+ allow(subject.ui).to receive(:ask).and_return(prompted_password)
176
+ end
177
+
178
+ it "passes password prompted" do
179
+ expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
180
+ expect(opts[:password]).to eq(prompted_password)
181
+ end.and_return(winrm_session)
182
+ subject.configure_session
183
+ end
184
+ end
185
+ end
186
+
187
+ context "when configuring the WinRM transport" do
188
+ before(:all) do
189
+ @winrm_session = Object.new
190
+ @winrm_session.define_singleton_method(:set_timeout){|timeout| ""}
191
+ end
192
+
193
+ context "kerberos option is set" do
194
+ let(:winrm_command_http) { Chef::Knife::Winrm.new([
195
+ '-m', 'localhost',
196
+ '-x', 'testuser',
197
+ '-P', 'testpassword',
198
+ '--winrm-authentication-protocol', 'basic',
199
+ '--kerberos-realm', 'realm',
200
+ 'echo helloworld'
201
+ ]) }
202
+
203
+ it "sets the transport to kerberos" do
204
+ expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5985/wsman', :kerberos, anything).and_return(@winrm_session)
205
+ winrm_command_http.configure_chef
206
+ winrm_command_http.configure_session
207
+ end
208
+ end
209
+
210
+ context "kerberos option is set but nil" do
211
+ let(:winrm_command_http) { Chef::Knife::Winrm.new([
212
+ '-m', 'localhost',
213
+ '-x', 'testuser',
214
+ '-P', 'testpassword',
215
+ '--winrm-authentication-protocol', 'basic',
216
+ 'echo helloworld'
217
+ ]) }
218
+
219
+ it "sets the transport to plaintext" do
220
+ winrm_command_http.config[:kerberos_realm] = nil
221
+ expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5985/wsman', :plaintext, anything).and_return(@winrm_session)
222
+ winrm_command_http.configure_chef
223
+ winrm_command_http.configure_session
224
+ end
225
+ end
226
+
227
+ context "on windows workstations" do
228
+ let(:protocol) { 'negotiate' }
229
+
230
+ before do
231
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
232
+ end
233
+
234
+ it "defaults to negotiate when on a Windows host" do
235
+ expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
236
+ expect(opts[:transport]).to eq(:sspinegotiate)
237
+ end.and_return(winrm_session)
238
+ subject.configure_session
239
+ end
240
+ end
241
+
242
+ context "on non-windows workstations" do
243
+ before do
244
+ allow(Chef::Platform).to receive(:windows?).and_return(false)
245
+ end
246
+
247
+ let(:winrm_command_http) { Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '-t', 'plaintext', '--winrm-authentication-protocol', 'basic', 'echo helloworld']) }
248
+
249
+ it "defaults to the http uri scheme" do
250
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :plaintext)).and_call_original
251
+ expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5985/wsman', anything, anything).and_return(@winrm_session)
252
+ winrm_command_http.configure_chef
253
+ winrm_command_http.configure_session
254
+ end
255
+
256
+ it "sets the operation timeout and verifes default" do
257
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :plaintext)).and_call_original
258
+ expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5985/wsman', anything, anything).and_return(@winrm_session)
259
+ expect(@winrm_session).to receive(:set_timeout).with(1800)
260
+ winrm_command_http.configure_chef
261
+ winrm_command_http.configure_session
262
+ end
263
+
264
+ it "sets the user specified winrm port" do
265
+ Chef::Config[:knife] = {winrm_port: "5988"}
266
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :plaintext)).and_call_original
267
+ expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5988/wsman', anything, anything).and_return(@winrm_session)
268
+ winrm_command_http.configure_chef
269
+ winrm_command_http.configure_session
270
+ end
271
+
272
+ let(:winrm_command_timeout) { Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '--winrm-authentication-protocol', 'basic', '--session-timeout', '10', 'echo helloworld']) }
273
+
274
+ it "sets operation timeout and verify 10 Minute timeout" do
275
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :plaintext)).and_call_original
276
+ expect(WinRM::WinRMWebService).to receive(:new).with('http://localhost:5985/wsman', anything, anything).and_return(@winrm_session)
277
+ expect(@winrm_session).to receive(:set_timeout).with(600)
278
+ winrm_command_timeout.configure_chef
279
+ winrm_command_timeout.configure_session
280
+ end
281
+
282
+ let(:winrm_command_https) { Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '--winrm-transport', 'ssl', 'echo helloworld']) }
283
+
284
+ it "uses the https uri scheme if the ssl transport is specified" do
285
+ Chef::Config[:knife] = {:winrm_transport => 'ssl'}
286
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
287
+ expect(WinRM::WinRMWebService).to receive(:new).with('https://localhost:5986/wsman', anything, anything).and_return(@winrm_session)
288
+ winrm_command_https.configure_chef
289
+ winrm_command_https.configure_session
290
+ end
291
+
292
+ it "uses the winrm port '5986' by default for ssl transport" do
293
+ Chef::Config[:knife] = {:winrm_transport => 'ssl'}
294
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
295
+ expect(WinRM::WinRMWebService).to receive(:new).with('https://localhost:5986/wsman', anything, anything).and_return(@winrm_session)
296
+ winrm_command_https.configure_chef
297
+ winrm_command_https.configure_session
298
+ end
299
+
300
+ it "defaults to validating the server when the ssl transport is used" do
301
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
302
+ expect(WinRM::WinRMWebService).to receive(:new).with(anything, anything, hash_including(:no_ssl_peer_verification => false)).and_return(@winrm_session)
303
+ winrm_command_https.configure_chef
304
+ winrm_command_https.configure_session
305
+ end
306
+
307
+ let(:winrm_command_verify_peer) { Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '--winrm-transport', 'ssl', '--winrm-ssl-verify-mode', 'verify_peer', 'echo helloworld'])}
308
+
309
+ it "validates the server when the ssl transport is used and the :winrm_ssl_verify_mode option is not configured to :verify_none" do
310
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
311
+ expect(WinRM::WinRMWebService).to receive(:new).with(anything, anything, hash_including(:no_ssl_peer_verification => false)).and_return(@winrm_session)
312
+ winrm_command_verify_peer.configure_chef
313
+ winrm_command_verify_peer.configure_session
314
+ end
315
+
316
+ context "when setting verify_none" do
317
+ let(:transport) { 'ssl' }
318
+
319
+ before { knife_args << '--winrm-ssl-verify-mode' << 'verify_none' }
320
+
321
+ it "does not validate the server when the ssl transport is used and the :winrm_ssl_verify_mode option is set to :verify_none" do
322
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
323
+ expect(WinRM::WinRMWebService).to receive(:new).with(anything, anything, hash_including(:no_ssl_peer_verification => true)).and_return(@winrm_session)
324
+ subject.configure_chef
325
+ subject.configure_session
326
+ end
327
+
328
+ it "prints warning output when the :winrm_ssl_verify_mode set to :verify_none to disable server validation" do
329
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
330
+ expect(WinRM::WinRMWebService).to receive(:new).with(anything, anything, hash_including(:no_ssl_peer_verification => true)).and_return(@winrm_session)
331
+ expect(subject).to receive(:warn_no_ssl_peer_verification)
332
+
333
+ subject.configure_chef
334
+ subject.configure_session
335
+ end
336
+
337
+ context "when transport is plaintext" do
338
+ let(:transport) { 'plaintext' }
339
+
340
+ it "does not print warning re ssl server validation" do
341
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :plaintext)).and_call_original
342
+ expect(WinRM::WinRMWebService).to receive(:new).and_return(winrm_service)
343
+ expect(subject).to_not receive(:warn_no_ssl_peer_verification)
344
+
345
+ subject.configure_chef
346
+ subject.configure_session
347
+ end
348
+ end
349
+ end
350
+
351
+ let(:winrm_command_ca_trust) { Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '--winrm-transport', 'ssl', '--ca-trust-file', '~/catrustroot', '--winrm-ssl-verify-mode', 'verify_none', 'echo helloworld'])}
352
+
353
+ it "validates the server when the ssl transport is used and the :ca_trust_file option is specified even if the :winrm_ssl_verify_mode option is set to :verify_none" do
354
+ expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:transport => :ssl)).and_call_original
355
+ expect(WinRM::WinRMWebService).to receive(:new).with(anything, anything, hash_including(:no_ssl_peer_verification => false)).and_return(@winrm_session)
356
+ winrm_command_ca_trust.configure_chef
357
+ winrm_command_ca_trust.configure_session
358
+ end
359
+ end
360
+ end
361
+ end
362
+
363
+ describe "#run" do
364
+ let(:session_opts) do
365
+ {
366
+ user: ".\\testuser",
367
+ password: "testpassword",
368
+ port: "5985",
369
+ transport: :plaintext,
370
+ host: "localhost"
371
+ }
372
+ end
373
+ let(:session) { Chef::Knife::WinrmSession.new(session_opts) }
374
+
375
+ before(:each) do
376
+ allow(Chef::Knife::WinrmSession).to receive(:new).and_return(session)
377
+ Chef::Config[:knife] = {:winrm_transport => 'plaintext'}
378
+ @winrm = Chef::Knife::Winrm.new(['-m', 'localhost', '-x', 'testuser', '-P', 'testpassword', '--winrm-authentication-protocol', 'basic', 'echo helloworld'])
379
+ end
380
+
381
+ it "returns with 0 if the command succeeds" do
382
+ allow(@winrm).to receive(:relay_winrm_command).and_return(0)
383
+ return_code = @winrm.run
384
+ expect(return_code).to be_zero
385
+ end
386
+
387
+ it "exits with exact exit status if the command fails and returns config is set to 0" do
388
+ command_status = 510
389
+
390
+ @winrm.config[:returns] = "0"
391
+ Chef::Config[:knife][:returns] = [0]
392
+
393
+ allow(@winrm).to receive(:relay_winrm_command)
394
+ allow(@winrm.ui).to receive(:error)
395
+ allow(session).to receive(:exit_code).and_return(command_status)
396
+ expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(command_status) }
397
+ end
398
+
399
+ it "exits with non-zero status if the command fails and returns config is set to 0" do
400
+ command_status = 1
401
+ @winrm.config[:returns] = "0,53"
402
+ Chef::Config[:knife][:returns] = [0,53]
403
+ allow(@winrm).to receive(:relay_winrm_command).and_return(command_status)
404
+ allow(@winrm.ui).to receive(:error)
405
+ allow(session).to receive(:exit_code).and_return(command_status)
406
+ expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(command_status) }
407
+ end
408
+
409
+ it "exits with a zero status if the command returns an expected non-zero status" do
410
+ command_status = 53
411
+ Chef::Config[:knife][:returns] = [0,53]
412
+ allow(@winrm).to receive(:relay_winrm_command).and_return(command_status)
413
+ allow(session).to receive(:exit_codes).and_return({"thishost" => command_status})
414
+ exit_code = @winrm.run
415
+ expect(exit_code).to be_zero
416
+ end
417
+
418
+ it "exits with a zero status if the command returns an expected non-zero status" do
419
+ command_status = 53
420
+ @winrm.config[:returns] = '0,53'
421
+ allow(@winrm).to receive(:relay_winrm_command).and_return(command_status)
422
+ allow(session).to receive(:exit_codes).and_return({"thishost" => command_status})
423
+ exit_code = @winrm.run
424
+ expect(exit_code).to be_zero
425
+ end
426
+
427
+ it "exits with 100 and no hint if command execution raises an exception other than 401" do
428
+ allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('', '500'))
429
+ allow(@winrm.ui).to receive(:error)
430
+ expect(@winrm.ui).to_not receive(:info)
431
+ expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(100) }
432
+ end
433
+
434
+ it "exits with 100 if command execution raises a 401" do
435
+ allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new('', '401'))
436
+ allow(@winrm.ui).to receive(:info)
437
+ allow(@winrm.ui).to receive(:error)
438
+ expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(100) }
439
+ end
440
+
441
+ it "exits with 401 if command execution raises a 401 and suppress_auth_failure is set to true" do
442
+ @winrm.config[:suppress_auth_failure] = true
443
+ allow(session).to receive(:relay_command).and_raise(WinRM::WinRMHTTPTransportError.new('', '401'))
444
+ expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(401) }
445
+ end
446
+
447
+ it "prints a hint on failure for negotiate authentication" do
448
+ @winrm.config[:winrm_authentication_protocol] = "negotiate"
449
+ @winrm.config[:winrm_transport] = "plaintext"
450
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
451
+ allow(session).to receive(:relay_command).and_raise(WinRM::WinRMAuthorizationError.new)
452
+ allow(@winrm.ui).to receive(:error)
453
+ allow(@winrm.ui).to receive(:info)
454
+ expect(@winrm.ui).to receive(:info).with(Chef::Knife::Winrm::FAILED_NOT_BASIC_HINT)
455
+ expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit)
456
+ end
457
+
458
+ it "prints a hint on failure for basic authentication" do
459
+ @winrm.config[:winrm_authentication_protocol] = "basic"
460
+ @winrm.config[:winrm_transport] = "plaintext"
461
+ allow(session).to receive(:relay_command).and_raise(WinRM::WinRMHTTPTransportError.new('', '401'))
462
+ allow(@winrm.ui).to receive(:error)
463
+ allow(@winrm.ui).to receive(:info)
464
+ expect(@winrm.ui).to receive(:info).with(Chef::Knife::Winrm::FAILED_BASIC_HINT)
465
+ expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit)
466
+ end
467
+
468
+ context "when winrm_authentication_protocol specified" do
469
+ before do
470
+ Chef::Config[:knife] = {:winrm_transport => 'plaintext'}
471
+ allow(@winrm).to receive(:relay_winrm_command).and_return(0)
472
+ end
473
+
474
+ it "sets sspinegotiate transport on windows for 'negotiate' authentication" do
475
+ @winrm.config[:winrm_authentication_protocol] = "negotiate"
476
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
477
+ allow(Chef::Knife::WinrmSession).to receive(:new) do |opts|
478
+ expect(opts[:disable_sspi]).to be(false)
479
+ expect(opts[:transport]).to be(:sspinegotiate)
480
+ end.and_return(session)
481
+ @winrm.run
482
+ end
483
+
484
+ it "does not have winrm opts transport set to sspinegotiate for unix" do
485
+ @winrm.config[:winrm_authentication_protocol] = "negotiate"
486
+ allow(Chef::Platform).to receive(:windows?).and_return(false)
487
+ allow(@winrm).to receive(:exit)
488
+ allow(Chef::Knife::WinrmSession).to receive(:new) do |opts|
489
+ expect(opts[:disable_sspi]).to be(true)
490
+ expect(opts[:transport]).to be(:plaintext)
491
+ end.and_return(session)
492
+ @winrm.run
493
+ end
494
+
495
+ it "disables sspi and skips the winrm monkey patch for 'ssl' transport and 'basic' authentication" do
496
+ @winrm.config[:winrm_authentication_protocol] = "basic"
497
+ @winrm.config[:winrm_transport] = "ssl"
498
+ @winrm.config[:winrm_port] = "5986"
499
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
500
+ allow(Chef::Knife::WinrmSession).to receive(:new) do |opts|
501
+ expect(opts[:port]).to be(@winrm.config[:winrm_port])
502
+ expect(opts[:transport]).to be(:ssl)
503
+ expect(opts[:disable_sspi]).to be(true)
504
+ expect(opts[:basic_auth_only]).to be(true)
505
+ end.and_return(session)
506
+ @winrm.run
507
+ end
508
+
509
+ it "applies winrm monkey patch on windows if 'negotiate' authentication and 'plaintext' transport is specified", :windows_only => true do
510
+ @winrm.config[:winrm_authentication_protocol] = "negotiate"
511
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
512
+ allow(@winrm.ui).to receive(:warn)
513
+ @winrm.run
514
+ end
515
+
516
+ it "raises an error if value is other than [basic, negotiate, kerberos]" do
517
+ @winrm.config[:winrm_authentication_protocol] = "invalid"
518
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
519
+ expect(@winrm.ui).to receive(:error)
520
+ expect { @winrm.run }.to raise_error(SystemExit)
521
+ end
522
+
523
+ it "skips the winrm monkey patch for 'basic' authentication" do
524
+ @winrm.config[:winrm_authentication_protocol] = "basic"
525
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
526
+ @winrm.run
527
+ end
528
+
529
+ it "skips the winrm monkey patch for 'kerberos' authentication" do
530
+ @winrm.config[:winrm_authentication_protocol] = "kerberos"
531
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
532
+ @winrm.run
533
+ end
534
+
535
+ it "skips the winrm monkey patch for 'ssl' transport and 'negotiate' authentication" do
536
+ @winrm.config[:winrm_authentication_protocol] = "negotiate"
537
+ @winrm.config[:winrm_transport] = "ssl"
538
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
539
+ @winrm.run
540
+ end
541
+
542
+ it "prints a warning on linux for unencrypted negotiate authentication" do
543
+ @winrm.config[:winrm_authentication_protocol] = "negotiate"
544
+ @winrm.config[:winrm_transport] = "plaintext"
545
+ allow(Chef::Platform).to receive(:windows?).and_return(false)
546
+ expect(@winrm.ui).to receive(:warn).once
547
+ expect { @winrm.run }.to_not raise_error(SystemExit)
548
+ end
549
+ end
550
+ end
551
+ end