knife-windows 1.1.0 → 1.1.1

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 (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