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.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +3 -0
- data/.travis.yml +30 -0
- data/CHANGELOG.md +147 -0
- data/DOC_CHANGES.md +22 -0
- data/Gemfile +13 -0
- data/LICENSE +201 -0
- data/README.md +430 -0
- data/RELEASE_NOTES.md +17 -0
- data/Rakefile +21 -0
- data/appveyor.yml +36 -0
- data/ci.gemfile +15 -0
- data/knife-winops.gemspec +26 -0
- data/lib/chef/knife/bootstrap/Chef_bootstrap.erb +44 -0
- data/lib/chef/knife/bootstrap/bootstrap.ps1 +134 -0
- data/lib/chef/knife/bootstrap/tail.cmd +15 -0
- data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +302 -0
- data/lib/chef/knife/bootstrap_windows_base.rb +473 -0
- data/lib/chef/knife/bootstrap_windows_ssh.rb +115 -0
- data/lib/chef/knife/bootstrap_windows_winrm.rb +102 -0
- data/lib/chef/knife/core/windows_bootstrap_context.rb +356 -0
- data/lib/chef/knife/knife_windows_base.rb +33 -0
- data/lib/chef/knife/windows_cert_generate.rb +155 -0
- data/lib/chef/knife/windows_cert_install.rb +68 -0
- data/lib/chef/knife/windows_helper.rb +36 -0
- data/lib/chef/knife/windows_listener_create.rb +107 -0
- data/lib/chef/knife/winrm.rb +127 -0
- data/lib/chef/knife/winrm_base.rb +128 -0
- data/lib/chef/knife/winrm_knife_base.rb +315 -0
- data/lib/chef/knife/winrm_session.rb +101 -0
- data/lib/chef/knife/winrm_shared_options.rb +54 -0
- data/lib/chef/knife/wsman_endpoint.rb +44 -0
- data/lib/chef/knife/wsman_test.rb +118 -0
- data/lib/knife-winops/path_helper.rb +242 -0
- data/lib/knife-winops/version.rb +6 -0
- data/spec/assets/fake_trusted_certs/excluded.txt +2 -0
- data/spec/assets/fake_trusted_certs/github.pem +42 -0
- data/spec/assets/fake_trusted_certs/google.crt +41 -0
- data/spec/assets/win_fake_trusted_cert_script.txt +89 -0
- data/spec/dummy_winrm_connection.rb +21 -0
- data/spec/functional/bootstrap_download_spec.rb +229 -0
- data/spec/spec_helper.rb +93 -0
- data/spec/unit/knife/bootstrap_options_spec.rb +164 -0
- data/spec/unit/knife/bootstrap_template_spec.rb +98 -0
- data/spec/unit/knife/bootstrap_windows_winrm_spec.rb +410 -0
- data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +292 -0
- data/spec/unit/knife/windows_cert_generate_spec.rb +90 -0
- data/spec/unit/knife/windows_cert_install_spec.rb +51 -0
- data/spec/unit/knife/windows_listener_create_spec.rb +76 -0
- data/spec/unit/knife/winrm_session_spec.rb +101 -0
- data/spec/unit/knife/winrm_spec.rb +494 -0
- data/spec/unit/knife/wsman_test_spec.rb +209 -0
- 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
|