knife-winops 2.0.0

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 (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +30 -0
  5. data/CHANGELOG.md +147 -0
  6. data/DOC_CHANGES.md +22 -0
  7. data/Gemfile +13 -0
  8. data/LICENSE +201 -0
  9. data/README.md +430 -0
  10. data/RELEASE_NOTES.md +17 -0
  11. data/Rakefile +21 -0
  12. data/appveyor.yml +36 -0
  13. data/ci.gemfile +15 -0
  14. data/knife-winops.gemspec +26 -0
  15. data/lib/chef/knife/bootstrap/Chef_bootstrap.erb +44 -0
  16. data/lib/chef/knife/bootstrap/bootstrap.ps1 +134 -0
  17. data/lib/chef/knife/bootstrap/tail.cmd +15 -0
  18. data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +302 -0
  19. data/lib/chef/knife/bootstrap_windows_base.rb +473 -0
  20. data/lib/chef/knife/bootstrap_windows_ssh.rb +115 -0
  21. data/lib/chef/knife/bootstrap_windows_winrm.rb +102 -0
  22. data/lib/chef/knife/core/windows_bootstrap_context.rb +356 -0
  23. data/lib/chef/knife/knife_windows_base.rb +33 -0
  24. data/lib/chef/knife/windows_cert_generate.rb +155 -0
  25. data/lib/chef/knife/windows_cert_install.rb +68 -0
  26. data/lib/chef/knife/windows_helper.rb +36 -0
  27. data/lib/chef/knife/windows_listener_create.rb +107 -0
  28. data/lib/chef/knife/winrm.rb +127 -0
  29. data/lib/chef/knife/winrm_base.rb +128 -0
  30. data/lib/chef/knife/winrm_knife_base.rb +315 -0
  31. data/lib/chef/knife/winrm_session.rb +101 -0
  32. data/lib/chef/knife/winrm_shared_options.rb +54 -0
  33. data/lib/chef/knife/wsman_endpoint.rb +44 -0
  34. data/lib/chef/knife/wsman_test.rb +118 -0
  35. data/lib/knife-winops/path_helper.rb +242 -0
  36. data/lib/knife-winops/version.rb +6 -0
  37. data/spec/assets/fake_trusted_certs/excluded.txt +2 -0
  38. data/spec/assets/fake_trusted_certs/github.pem +42 -0
  39. data/spec/assets/fake_trusted_certs/google.crt +41 -0
  40. data/spec/assets/win_fake_trusted_cert_script.txt +89 -0
  41. data/spec/dummy_winrm_connection.rb +21 -0
  42. data/spec/functional/bootstrap_download_spec.rb +229 -0
  43. data/spec/spec_helper.rb +93 -0
  44. data/spec/unit/knife/bootstrap_options_spec.rb +164 -0
  45. data/spec/unit/knife/bootstrap_template_spec.rb +98 -0
  46. data/spec/unit/knife/bootstrap_windows_winrm_spec.rb +410 -0
  47. data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +292 -0
  48. data/spec/unit/knife/windows_cert_generate_spec.rb +90 -0
  49. data/spec/unit/knife/windows_cert_install_spec.rb +51 -0
  50. data/spec/unit/knife/windows_listener_create_spec.rb +76 -0
  51. data/spec/unit/knife/winrm_session_spec.rb +101 -0
  52. data/spec/unit/knife/winrm_spec.rb +494 -0
  53. data/spec/unit/knife/wsman_test_spec.rb +209 -0
  54. metadata +157 -0
@@ -0,0 +1,292 @@
1
+ #
2
+ # Original knife-windows author:: Bryan McLellan <btm@loftninjas.org>
3
+ # Copyright:: Copyright (c) 2014-2016 Chef Software, 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/core/windows_bootstrap_context'
21
+ describe Chef::Knife::Core::WindowsBootstrapContext do
22
+ let(:mock_bootstrap_context) { Chef::Knife::Core::WindowsBootstrapContext.new({ }, nil, { :knife => {} }) }
23
+
24
+ before do
25
+ allow(Chef::Knife::Core::WindowsBootstrapContext).to receive(:new).and_return(mock_bootstrap_context)
26
+ end
27
+
28
+ describe "fips" do
29
+ before do
30
+ Chef::Config[:fips] = fips_mode
31
+ end
32
+
33
+ after do
34
+ Chef::Config.reset!
35
+ end
36
+
37
+ context "when fips is set" do
38
+ let(:fips_mode) { true }
39
+
40
+ it "sets fips mode in the client.rb" do
41
+ expect(mock_bootstrap_context.config_content).to match(/fips true/)
42
+ end
43
+ end
44
+
45
+ context "when fips is not set" do
46
+ let(:fips_mode) { false }
47
+
48
+ it "sets fips mode in the client.rb" do
49
+ expect(mock_bootstrap_context.config_content).not_to match(/fips true/)
50
+ end
51
+ end
52
+ end
53
+
54
+ describe "trusted_certs_script" do
55
+ let(:mock_cert_dir) { ::File.absolute_path(::File.join('spec','assets','fake_trusted_certs')) }
56
+ let(:script_output) { mock_bootstrap_context.trusted_certs_script }
57
+ let(:crt_files) { ::Dir.glob(::File.join(mock_cert_dir, "*.crt")) }
58
+ let(:pem_files) { ::Dir.glob(::File.join(mock_cert_dir, "*.pem")) }
59
+ let(:other_files) { ::Dir.glob(::File.join(mock_cert_dir, "*"))-crt_files-pem_files }
60
+
61
+ before do
62
+ mock_bootstrap_context.instance_variable_set(:@chef_config, Mash.new(:trusted_certs_dir => mock_cert_dir))
63
+ end
64
+
65
+ it "should echo every .crt file in the trusted_certs directory" do
66
+ crt_files.each do |f|
67
+ echo_file = ::File.read(f).gsub(/^/, "echo.")
68
+ expect(script_output).to include(::File.join('trusted_certs',::File.basename(f)))
69
+ expect(script_output).to include(echo_file)
70
+ end
71
+ end
72
+
73
+ it "should echo every .pem file in the trusted_certs directory" do
74
+ pem_files.each do |f|
75
+ echo_file = ::File.read(f).gsub(/^/, "echo.")
76
+ expect(script_output).to include(::File.join('trusted_certs',::File.basename(f)))
77
+ expect(script_output).to include(echo_file)
78
+ end
79
+ end
80
+
81
+ it "should not echo files which aren't .crt or .pem files" do
82
+ other_files.each do |f|
83
+ echo_file = ::File.read(f).gsub(/^/, "echo.")
84
+ expect(script_output).to_not include(::File.join('trusted_certs',::File.basename(f)))
85
+ expect(script_output).to_not include(echo_file)
86
+ end
87
+ end
88
+ end
89
+
90
+ describe "validation_key" do
91
+ before do
92
+ mock_bootstrap_context.instance_variable_set(:@config, Mash.new(:validation_key => "C:\\chef\\key.pem"))
93
+ end
94
+
95
+ it "should return false if validation_key does not exist" do
96
+ allow(::File).to receive(:expand_path)
97
+ allow(::File).to receive(:exist?).and_return(false)
98
+ expect(mock_bootstrap_context.validation_key).to eq(false)
99
+ end
100
+ end
101
+
102
+ describe "#get_log_location" do
103
+
104
+ context "when config_log_location value is nil" do
105
+ it "sets STDOUT in client.rb as default" do
106
+ mock_bootstrap_context.instance_variable_set(:@chef_config, Mash.new(:config_log_location => nil))
107
+ expect(mock_bootstrap_context.get_log_location).to eq("STDOUT\n")
108
+ end
109
+ end
110
+
111
+ context "when config_log_location value is empty" do
112
+ it "sets STDOUT in client.rb as default" do
113
+ mock_bootstrap_context.instance_variable_set(:@chef_config, Mash.new(:config_log_location => ""))
114
+ expect(mock_bootstrap_context.get_log_location).to eq("STDOUT\n")
115
+ end
116
+ end
117
+
118
+ context "when config_log_location value is STDOUT" do
119
+ it "sets STDOUT in client.rb" do
120
+ mock_bootstrap_context.instance_variable_set(:@chef_config, Mash.new(:config_log_location => STDOUT))
121
+ expect(mock_bootstrap_context.get_log_location).to eq("STDOUT\n")
122
+ end
123
+ end
124
+
125
+ context "when config_log_location value is STDERR" do
126
+ it "sets STDERR in client.rb" do
127
+ mock_bootstrap_context.instance_variable_set(:@chef_config, Mash.new(:config_log_location => STDERR))
128
+ expect(mock_bootstrap_context.get_log_location).to eq("STDERR\n")
129
+ end
130
+ end
131
+
132
+ context "when config_log_location value is path to a file" do
133
+ it "sets file path in client.rb" do
134
+ mock_bootstrap_context.instance_variable_set(:@chef_config, Mash.new(:config_log_location => "C:\\chef\\chef.log"))
135
+ expect(mock_bootstrap_context.get_log_location).to eq("\"C:\\chef\\chef.log\"\n")
136
+ end
137
+ end
138
+
139
+ context "when config_log_location value is :win_evt" do
140
+ it "sets :win_evt in client.rb" do
141
+ mock_bootstrap_context.instance_variable_set(:@chef_config, Mash.new(:config_log_location => :win_evt))
142
+ expect(mock_bootstrap_context.get_log_location).to eq(":win_evt\n")
143
+ end
144
+ end
145
+
146
+ context "when config_log_location value is :syslog" do
147
+ it "raise error with message and exit" do
148
+ mock_bootstrap_context.instance_variable_set(:@chef_config, Mash.new(:config_log_location => :syslog))
149
+ expect { mock_bootstrap_context.get_log_location }.to raise_error("syslog is not supported for log_location on Windows OS\n")
150
+ end
151
+ end
152
+
153
+ end
154
+
155
+ describe "#config_content" do
156
+ before do
157
+ mock_bootstrap_context.instance_variable_set(:@chef_config, Mash.new(:config_log_level => :info,
158
+ :config_log_location => STDOUT,
159
+ :chef_server_url => "http://chef.example.com:4444",
160
+ :validation_client_name => "chef-validator-testing",
161
+ :file_cache_path => "c:/chef/cache",
162
+ :file_backup_path => "c:/chef/backup",
163
+ :cache_options => ({:path => "c:/chef/cache/checksums", :skip_expires => true})
164
+ ))
165
+ end
166
+
167
+ it "generates the config file data" do
168
+ expected = <<-EXPECTED
169
+ echo.chef_server_url "http://chef.example.com:4444"
170
+ echo.validation_client_name "chef-validator-testing"
171
+ echo.file_cache_path "c:/chef/cache"
172
+ echo.file_backup_path "c:/chef/backup"
173
+ echo.cache_options ^({:path =^> "c:/chef/cache/checksums", :skip_expires =^> true}^)
174
+ echo.# Using default node name ^(fqdn^)
175
+ echo.log_level :info
176
+ echo.log_location STDOUT
177
+ EXPECTED
178
+ expect(mock_bootstrap_context.config_content).to eq expected
179
+ end
180
+ end
181
+
182
+ describe "chef_version_in_url" do
183
+ it "returns the major version of the current version of Chef" do
184
+ stub_const("Chef::VERSION", '11.1.2')
185
+ expect(mock_bootstrap_context.chef_version_in_url).to eq("&v=11")
186
+ end
187
+
188
+ it "does not add prerelease if the version of Chef installed is a prerelease" do
189
+ stub_const("Chef::VERSION", '42.0.1.alpha.1')
190
+ expect(mock_bootstrap_context.chef_version_in_url).not_to match(/&prerelease=true/)
191
+ end
192
+
193
+ it "does add prerelease if the version specified to be installed is a prerelease" do
194
+ allow(mock_bootstrap_context).to receive(:knife_config).and_return(Mash.new(:bootstrap_version => "12.0.0.alpha.1"))
195
+ expect(mock_bootstrap_context.chef_version_in_url).to eq("&v=12.0.0.alpha.1&prerelease=true")
196
+ end
197
+
198
+ context "when the prerelease config option is set" do
199
+ before do
200
+ mock_bootstrap_context.instance_variable_set(:@config, Mash.new(:prerelease => true))
201
+ end
202
+
203
+ it "sets prerelease to true in the returned string" do
204
+ expect(mock_bootstrap_context.chef_version_in_url).to eq("&prerelease=true")
205
+ end
206
+ end
207
+ end
208
+
209
+ describe "msi_url" do
210
+ context "when config option is not set" do
211
+ before do
212
+ expect(mock_bootstrap_context).to receive(:chef_version_in_url).and_return("&v=something")
213
+ end
214
+
215
+ it "returns a chef.io msi url with minimal url parameters" do
216
+ reference_url = "https://www.chef.io/chef/download?p=windows&v=something"
217
+ expect(mock_bootstrap_context.msi_url).to eq(reference_url)
218
+ end
219
+
220
+ it "returns a chef.io msi url with provided url parameters substituted" do
221
+ reference_url = "https://www.chef.io/chef/download?p=windows&pv=machine&m=arch&DownloadContext=ctx&v=something"
222
+ expect(mock_bootstrap_context.msi_url('machine', 'arch', 'ctx')).to eq(reference_url)
223
+ end
224
+ end
225
+
226
+ context "when msi_url config option is set" do
227
+ let(:custom_url) { "file://something" }
228
+
229
+ before do
230
+ mock_bootstrap_context.instance_variable_set(:@config, Mash.new(:msi_url => custom_url))
231
+ end
232
+
233
+ it "returns the overriden url" do
234
+ expect(mock_bootstrap_context.msi_url).to eq(custom_url)
235
+ end
236
+
237
+ it "doesn't introduce any unnecessary query parameters if provided by the template" do
238
+ expect(mock_bootstrap_context.msi_url('machine', 'arch', 'ctx')).to eq(custom_url)
239
+ end
240
+ end
241
+ end
242
+
243
+ describe "bootstrap_install_command for bootstrap through WinRM" do
244
+ context "when bootstrap_install_command option is passed on CLI" do
245
+ let(:bootstrap) { Chef::Knife::BootstrapWindowsWinrm.new(['--bootstrap-install-command', 'chef-client']) }
246
+ before do
247
+ bootstrap.config[:bootstrap_install_command] = "chef-client"
248
+ end
249
+
250
+ it "sets the bootstrap_install_command option under Chef::Config::Knife object" do
251
+ expect(Chef::Config[:knife][:bootstrap_install_command]).to eq("chef-client")
252
+ end
253
+
254
+ after do
255
+ bootstrap.config.delete(:bootstrap_install_command)
256
+ Chef::Config[:knife].delete(:bootstrap_install_command)
257
+ end
258
+ end
259
+
260
+ context "when bootstrap_install_command option is not passed on CLI" do
261
+ let(:bootstrap) { Chef::Knife::BootstrapWindowsWinrm.new([]) }
262
+ it "does not set the bootstrap_install_command option under Chef::Config::Knife object" do
263
+ expect(Chef::Config[:knife][:bootstrap_install_command]). to eq(nil)
264
+ end
265
+ end
266
+ end
267
+
268
+ describe "bootstrap_install_command for bootstrap through SSH" do
269
+ context "when bootstrap_install_command option is passed on CLI" do
270
+ let(:bootstrap) { Chef::Knife::BootstrapWindowsSsh.new(['--bootstrap-install-command', 'chef-client']) }
271
+ before do
272
+ bootstrap.config[:bootstrap_install_command] = "chef-client"
273
+ end
274
+
275
+ it "sets the bootstrap_install_command option under Chef::Config::Knife object" do
276
+ expect(Chef::Config[:knife][:bootstrap_install_command]).to eq("chef-client")
277
+ end
278
+
279
+ after do
280
+ bootstrap.config.delete(:bootstrap_install_command)
281
+ Chef::Config[:knife].delete(:bootstrap_install_command)
282
+ end
283
+ end
284
+
285
+ context "when bootstrap_install_command option is not passed on CLI" do
286
+ let(:bootstrap) { Chef::Knife::BootstrapWindowsSsh.new([]) }
287
+ it "does not set the bootstrap_install_command option under Chef::Config::Knife object" do
288
+ expect(Chef::Config[:knife][:bootstrap_install_command]). to eq(nil)
289
+ end
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,90 @@
1
+ #
2
+ # Original knife-windows author:: Mukta Aphale <mukta.aphale@clogeny.com>
3
+ # Copyright:: Copyright (c) 2014-2016 Chef Software, 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_generate'
21
+ require 'openssl'
22
+
23
+ describe Chef::Knife::WindowsCertGenerate do
24
+ before(:all) do
25
+ @certgen = Chef::Knife::WindowsCertGenerate.new(["-H","something.mydomain.com"])
26
+ end
27
+
28
+ it "generates RSA key pair" do
29
+ @certgen.config[:key_length] = 2048
30
+ key = @certgen.generate_keypair
31
+ expect(key).to be_instance_of OpenSSL::PKey::RSA
32
+ end
33
+
34
+ it "generates X509 certificate" do
35
+ @certgen.config[:domain] = "test.com"
36
+ @certgen.config[:cert_validity] = "24"
37
+ key = @certgen.generate_keypair
38
+ certificate = @certgen.generate_certificate key
39
+ expect(certificate).to be_instance_of OpenSSL::X509::Certificate
40
+ end
41
+
42
+ it "writes certificate to file" do
43
+ expect(File).to receive(:open).exactly(3).times
44
+ cert = double(OpenSSL::X509::Certificate.new)
45
+ key = double(OpenSSL::PKey::RSA.new)
46
+ @certgen.config[:cert_passphrase] = "password"
47
+ expect(OpenSSL::PKCS12).to receive(:create).with("password", "winrmcert", key, cert)
48
+ @certgen.write_certificate_to_file cert, "test", key
49
+ end
50
+
51
+ context "when creating certificate files" do
52
+ before do
53
+ @certgen.thumbprint = "TEST_THUMBPRINT"
54
+ allow(Dir).to receive(:glob).and_return([])
55
+ allow(@certgen).to receive(:generate_keypair)
56
+ allow(@certgen).to receive(:generate_certificate)
57
+ expect(@certgen.ui).to receive(:info).with("Generated Certificates:")
58
+ expect(@certgen.ui).to receive(:info).with("- winrmcert.pfx - PKCS12 format key pair. Contains public and private keys, can be used with an SSL server.")
59
+ expect(@certgen.ui).to receive(:info).with("- winrmcert.b64 - Base64 encoded PKCS12 key pair. Contains public and private keys, used by some cloud provider API's to configure SSL servers.")
60
+ expect(@certgen.ui).to receive(:info).with("- winrmcert.pem - Base64 encoded public certificate only. Required by the client to connect to the server.")
61
+ expect(@certgen.ui).to receive(:info).with("Certificate Thumbprint: TEST_THUMBPRINT")
62
+ end
63
+
64
+ it "writes out certificates" do
65
+ @certgen.config[:output_file] = 'winrmcert'
66
+
67
+ expect(@certgen).to receive(:certificates_already_exist?).and_return(false)
68
+ expect(@certgen).to receive(:write_certificate_to_file)
69
+ @certgen.run
70
+ end
71
+
72
+ it "prompts when certificates already exist" do
73
+ file_path = 'winrmcert'
74
+ @certgen.config[:output_file] = file_path
75
+
76
+ allow(Dir).to receive(:glob).and_return([file_path])
77
+ expect(@certgen).to receive(:confirm).with("Do you really want to overwrite existing certificates")
78
+ expect(@certgen).to receive(:write_certificate_to_file)
79
+ @certgen.run
80
+ end
81
+
82
+ it "creates certificate on specified file path" do
83
+ file_path = "/tmp/winrmcert"
84
+ @certgen.name_args = [file_path]
85
+
86
+ expect(@certgen).to receive(:write_certificate_to_file) # FIXME: this should be testing that we get /tmp/winrmcert as the filename
87
+ @certgen.run
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,51 @@
1
+ #
2
+ # Original knife-windows author:: Mukta Aphale <mukta.aphale@clogeny.com>
3
+ # Copyright:: Copyright (c) 2014-2016 Chef Software, 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
@@ -0,0 +1,76 @@
1
+ #
2
+ # Original knife-windows author:: Mukta Aphale <mukta.aphale@clogeny.com>
3
+ # Copyright:: Copyright (c) 2014-2016 Chef Software, 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