knife-windows 3.0.6 → 3.0.10
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 +4 -4
- data/lib/chef/knife/bootstrap_windows_base.rb +87 -86
- data/lib/chef/knife/bootstrap_windows_ssh.rb +43 -43
- data/lib/chef/knife/bootstrap_windows_winrm.rb +16 -17
- data/lib/chef/knife/knife_windows_base.rb +0 -1
- data/lib/chef/knife/windows_cert_generate.rb +31 -31
- data/lib/chef/knife/windows_cert_install.rb +6 -6
- data/lib/chef/knife/windows_helper.rb +8 -8
- data/lib/chef/knife/windows_listener_create.rb +24 -24
- data/lib/chef/knife/winrm.rb +17 -17
- data/lib/chef/knife/winrm_base.rb +64 -62
- data/lib/chef/knife/winrm_knife_base.rb +41 -41
- data/lib/chef/knife/winrm_session.rb +7 -7
- data/lib/chef/knife/winrm_shared_options.rb +17 -17
- data/lib/chef/knife/wsman_endpoint.rb +1 -1
- data/lib/chef/knife/wsman_test.rb +10 -10
- data/lib/knife-windows/version.rb +2 -2
- data/spec/dummy_winrm_connection.rb +0 -1
- data/spec/spec_helper.rb +5 -80
- data/spec/unit/knife/windows_cert_generate_spec.rb +6 -6
- data/spec/unit/knife/windows_cert_install_spec.rb +2 -2
- data/spec/unit/knife/windows_listener_create_spec.rb +2 -2
- data/spec/unit/knife/winrm_session_spec.rb +6 -7
- data/spec/unit/knife/winrm_spec.rb +91 -87
- data/spec/unit/knife/wsman_test_spec.rb +43 -43
- metadata +2 -2
@@ -16,9 +16,9 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
19
|
+
require "chef/application"
|
20
|
+
require "winrm"
|
21
|
+
require "winrm-elevated"
|
22
22
|
|
23
23
|
class Chef
|
24
24
|
class Knife
|
@@ -34,10 +34,10 @@ class Chef
|
|
34
34
|
@shell_args = [ options[:shell] ]
|
35
35
|
@shell_args << { codepage: options[:codepage] } if options[:shell] == :cmd
|
36
36
|
url = "#{options[:host]}:#{options[:port]}/wsman"
|
37
|
-
scheme = options[:transport] == :ssl ?
|
37
|
+
scheme = options[:transport] == :ssl ? "https" : "http"
|
38
38
|
@endpoint = "#{scheme}://#{url}"
|
39
39
|
|
40
|
-
opts =
|
40
|
+
opts = {}
|
41
41
|
opts = {
|
42
42
|
user: @user,
|
43
43
|
password: options[:password],
|
@@ -46,9 +46,9 @@ class Chef
|
|
46
46
|
no_ssl_peer_verification: options[:no_ssl_peer_verification],
|
47
47
|
ssl_peer_fingerprint: options[:ssl_peer_fingerprint],
|
48
48
|
endpoint: endpoint,
|
49
|
-
transport: options[:transport]
|
49
|
+
transport: options[:transport],
|
50
50
|
}
|
51
|
-
options[:transport] == :kerberos ? opts.merge!({:
|
51
|
+
options[:transport] == :kerberos ? opts.merge!({ service: options[:service], realm: options[:realm] }) : opts.merge!({ ca_trust_path: options[:ca_trust_path] })
|
52
52
|
opts[:operation_timeout] = options[:operation_timeout] if options[:operation_timeout]
|
53
53
|
Chef::Log.debug("WinRM::WinRMWebService options: #{opts}")
|
54
54
|
Chef::Log.debug("Endpoint: #{endpoint}")
|
@@ -16,9 +16,9 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
19
|
+
require "chef/knife"
|
20
|
+
require "chef/encrypted_data_bag_item"
|
21
|
+
require "kconv"
|
22
22
|
|
23
23
|
class Chef
|
24
24
|
class Knife
|
@@ -28,24 +28,24 @@ class Chef
|
|
28
28
|
def self.included(includer)
|
29
29
|
includer.class_eval do
|
30
30
|
option :manual,
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
31
|
+
short: "-m",
|
32
|
+
long: "--manual-list",
|
33
|
+
boolean: true,
|
34
|
+
description: "QUERY is a space separated list of servers",
|
35
|
+
default: false
|
36
36
|
|
37
37
|
option :attribute,
|
38
|
-
:
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
38
|
+
short: "-a ATTR",
|
39
|
+
long: "--attribute ATTR",
|
40
|
+
description: "The attribute to use for opening the connection - default is fqdn",
|
41
|
+
default: "fqdn"
|
42
42
|
|
43
43
|
option :concurrency,
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
47
|
-
:
|
48
|
-
:
|
44
|
+
short: "-C NUM",
|
45
|
+
long: "--concurrency NUM",
|
46
|
+
description: "The number of allowed concurrent connections",
|
47
|
+
default: 1,
|
48
|
+
proc: lambda { |o| o.to_i }
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -16,10 +16,10 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require_relative
|
22
|
-
require_relative
|
19
|
+
require "httpclient"
|
20
|
+
require "chef/knife"
|
21
|
+
require_relative "winrm_knife_base"
|
22
|
+
require_relative "wsman_endpoint"
|
23
23
|
|
24
24
|
class Chef
|
25
25
|
class Knife
|
@@ -28,7 +28,7 @@ class Chef
|
|
28
28
|
include Chef::Knife::WinrmCommandSharedFunctions
|
29
29
|
|
30
30
|
deps do
|
31
|
-
require
|
31
|
+
require "chef/search/query"
|
32
32
|
end
|
33
33
|
|
34
34
|
banner "knife wsman test QUERY (options)"
|
@@ -36,7 +36,7 @@ class Chef
|
|
36
36
|
def run
|
37
37
|
# pass a dummy password to avoid prompt for password
|
38
38
|
# but it does nothing
|
39
|
-
@config[:winrm_password] =
|
39
|
+
@config[:winrm_password] = "cute_little_kittens"
|
40
40
|
|
41
41
|
configure_session
|
42
42
|
verify_wsman_accessiblity_for_nodes
|
@@ -81,8 +81,8 @@ class Chef
|
|
81
81
|
def post_identity_request(endpoint)
|
82
82
|
xml = '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd"><s:Header/><s:Body><wsmid:Identify/></s:Body></s:Envelope>'
|
83
83
|
header = {
|
84
|
-
|
85
|
-
|
84
|
+
"WSMANIDENTIFY" => "unauthenticated",
|
85
|
+
"Content-Type" => "application/soap+xml; charset=UTF-8",
|
86
86
|
}
|
87
87
|
|
88
88
|
client = HTTPClient.new
|
@@ -101,7 +101,7 @@ class Chef
|
|
101
101
|
doc = REXML::Document.new(response.body)
|
102
102
|
output_object.protocol_version = search_xpath(doc, "//wsmid:ProtocolVersion")
|
103
103
|
output_object.product_version = search_xpath(doc, "//wsmid:ProductVersion")
|
104
|
-
output_object.product_vendor
|
104
|
+
output_object.product_vendor = search_xpath(doc, "//wsmid:ProductVendor")
|
105
105
|
if output_object.protocol_version.to_s.strip.length == 0
|
106
106
|
output_object.error_message = "Endpoint #{node.endpoint} on #{node.host} does not appear to be a WSMAN endpoint. Response body was #{response.body}"
|
107
107
|
end
|
@@ -111,7 +111,7 @@ class Chef
|
|
111
111
|
|
112
112
|
def search_xpath(document, property_name)
|
113
113
|
result = REXML::XPath.match(document, property_name)
|
114
|
-
result[0].nil? ?
|
114
|
+
result[0].nil? ? "" : result[0].text
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
|
2
2
|
# Author:: Adam Edwards (<adamed@chef.io>)
|
3
|
-
# Copyright:: Copyright (c) 2012-
|
3
|
+
# Copyright:: Copyright (c) 2012-2020 Chef Software, Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -17,90 +17,15 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
require_relative '../lib/chef/knife/winrm'
|
25
|
-
require_relative '../lib/chef/knife/wsman_test'
|
26
|
-
|
27
|
-
if windows?
|
28
|
-
require 'ruby-wmi'
|
29
|
-
end
|
30
|
-
|
31
|
-
def windows2012?
|
32
|
-
is_win2k12 = false
|
33
|
-
|
34
|
-
if windows?
|
35
|
-
this_operating_system = WMI::Win32_OperatingSystem.find(:first)
|
36
|
-
os_version = this_operating_system.send('Version')
|
37
|
-
|
38
|
-
# The operating system version is a string in the following form
|
39
|
-
# that can be split into components based on the '.' delimiter:
|
40
|
-
# MajorVersionNumber.MinorVersionNumber.BuildNumber
|
41
|
-
os_version_components = os_version.split('.')
|
42
|
-
|
43
|
-
if os_version_components.length < 2
|
44
|
-
raise 'WMI returned a Windows version from Win32_OperatingSystem.Version ' +
|
45
|
-
'with an unexpected format. The Windows version could not be determined.'
|
46
|
-
end
|
47
|
-
|
48
|
-
# Windows 6.2 is Windows Server 2012, so test the major and
|
49
|
-
# minor version components
|
50
|
-
is_win2k12 = os_version_components[0] == '6' && os_version_components[1] == '2'
|
51
|
-
end
|
52
|
-
|
53
|
-
is_win2k12
|
54
|
-
end
|
55
|
-
|
56
|
-
def windows2016?
|
57
|
-
is_win2k16 = false
|
58
|
-
|
59
|
-
if windows?
|
60
|
-
this_operating_system = WMI::Win32_OperatingSystem.find(:first)
|
61
|
-
os_version = this_operating_system.send('Version')
|
62
|
-
|
63
|
-
# The operating system version is a string in the following form
|
64
|
-
# that can be split into components based on the '.' delimiter:
|
65
|
-
# MajorVersionNumber.MinorVersionNumber.BuildNumber
|
66
|
-
os_version_components = os_version.split('.')
|
67
|
-
|
68
|
-
if os_version_components.length < 2
|
69
|
-
raise 'WMI returned a Windows version from Win32_OperatingSystem.Version ' +
|
70
|
-
'with an unexpected format. The Windows version could not be determined.'
|
71
|
-
end
|
72
|
-
|
73
|
-
# Windows 10.0 is Windows Server 2016, so test the major and
|
74
|
-
# minor version components
|
75
|
-
is_win2k16 = os_version_components[0] == '10' && os_version_components[1] == '0'
|
76
|
-
end
|
77
|
-
|
78
|
-
is_win2k16
|
79
|
-
end
|
80
|
-
|
81
|
-
def chef_gte_13?
|
82
|
-
Gem::Version.new(Chef::VERSION) >= Gem::Version.new('13')
|
83
|
-
end
|
84
|
-
|
85
|
-
def chef_lt_14?
|
86
|
-
Gem::Version.new(Chef::VERSION) < Gem::Version.new('14')
|
87
|
-
end
|
88
|
-
|
89
|
-
def chef_gte_14?
|
90
|
-
Gem::Version.new(Chef::VERSION) >= Gem::Version.new('14')
|
91
|
-
end
|
20
|
+
require_relative "../lib/chef/knife/winrm"
|
21
|
+
require_relative "../lib/chef/knife/wsman_test"
|
92
22
|
|
93
23
|
def sample_data(file_name)
|
94
|
-
file =
|
24
|
+
file = File.expand_path(File.dirname("spec/assets/*")) + "/#{file_name}"
|
95
25
|
File.read(file)
|
96
26
|
end
|
97
27
|
|
98
28
|
RSpec.configure do |config|
|
99
29
|
config.run_all_when_everything_filtered = true
|
100
|
-
config.filter_run :
|
101
|
-
config.filter_run_excluding :windows_only => true unless windows?
|
102
|
-
config.filter_run_excluding :windows_2012_only => true unless windows2012?
|
103
|
-
config.filter_run_excluding :chef_gte_13_only => true unless chef_gte_13?
|
104
|
-
config.filter_run_excluding :chef_lt_14_only => true unless chef_lt_14?
|
105
|
-
config.filter_run_excluding :chef_gte_14_only => true unless chef_gte_14?
|
30
|
+
config.filter_run focus: true
|
106
31
|
end
|
@@ -16,13 +16,13 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
19
|
+
require "spec_helper"
|
20
|
+
require "chef/knife/windows_cert_generate"
|
21
|
+
require "openssl"
|
22
22
|
|
23
23
|
describe Chef::Knife::WindowsCertGenerate do
|
24
24
|
before(:all) do
|
25
|
-
@certgen = Chef::Knife::WindowsCertGenerate.new(["-H","something.mydomain.com"])
|
25
|
+
@certgen = Chef::Knife::WindowsCertGenerate.new(["-H", "something.mydomain.com"])
|
26
26
|
end
|
27
27
|
|
28
28
|
it "generates RSA key pair" do
|
@@ -62,7 +62,7 @@ describe Chef::Knife::WindowsCertGenerate do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
it "writes out certificates" do
|
65
|
-
@certgen.config[:output_file] =
|
65
|
+
@certgen.config[:output_file] = "winrmcert"
|
66
66
|
|
67
67
|
expect(@certgen).to receive(:certificates_already_exist?).and_return(false)
|
68
68
|
expect(@certgen).to receive(:write_certificate_to_file)
|
@@ -70,7 +70,7 @@ describe Chef::Knife::WindowsCertGenerate do
|
|
70
70
|
end
|
71
71
|
|
72
72
|
it "prompts when certificates already exist" do
|
73
|
-
file_path =
|
73
|
+
file_path = "winrmcert"
|
74
74
|
@certgen.config[:output_file] = file_path
|
75
75
|
|
76
76
|
allow(Dir).to receive(:glob).and_return([file_path])
|
@@ -16,8 +16,8 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
19
|
+
require "spec_helper"
|
20
|
+
require "chef/knife/windows_cert_install"
|
21
21
|
|
22
22
|
describe Chef::Knife::WindowsCertInstall do
|
23
23
|
context "on Windows" do
|
@@ -16,8 +16,8 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
19
|
+
require "spec_helper"
|
20
|
+
require "chef/knife/windows_listener_create"
|
21
21
|
|
22
22
|
describe Chef::Knife::WindowsListenerCreate do
|
23
23
|
context "on Windows" do
|
@@ -16,12 +16,11 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
19
|
+
require "spec_helper"
|
20
|
+
require "dummy_winrm_connection"
|
21
21
|
|
22
22
|
Chef::Knife::Winrm.load_deps
|
23
23
|
|
24
|
-
|
25
24
|
describe Chef::Knife::WinrmSession do
|
26
25
|
let(:winrm_connection) { Dummy::Connection.new }
|
27
26
|
let(:options) { { transport: :plaintext } }
|
@@ -39,8 +38,8 @@ describe Chef::Knife::WinrmSession do
|
|
39
38
|
|
40
39
|
describe "#initialize" do
|
41
40
|
context "when a proxy is configured" do
|
42
|
-
let(:proxy_uri) {
|
43
|
-
let(:ssl_policy) { double(
|
41
|
+
let(:proxy_uri) { "blah.com" }
|
42
|
+
let(:ssl_policy) { double("DefaultSSLPolicy", set_custom_certs: nil) }
|
44
43
|
|
45
44
|
before do
|
46
45
|
Chef::Config[:http_proxy] = proxy_uri
|
@@ -48,7 +47,7 @@ describe Chef::Knife::WinrmSession do
|
|
48
47
|
|
49
48
|
it "sets the http_proxy to the configured proxy" do
|
50
49
|
subject
|
51
|
-
expect(ENV[
|
50
|
+
expect(ENV["HTTP_PROXY"]).to eq("http://#{proxy_uri}")
|
52
51
|
end
|
53
52
|
|
54
53
|
it "sets the ssl policy on the winrm client" do
|
@@ -69,7 +68,7 @@ describe Chef::Knife::WinrmSession do
|
|
69
68
|
end
|
70
69
|
|
71
70
|
it "exits with 401 if command execution raises a 401" do
|
72
|
-
expect(winrm_connection).to receive(:shell).and_raise(WinRM::WinRMHTTPTransportError.new(
|
71
|
+
expect(winrm_connection).to receive(:shell).and_raise(WinRM::WinRMHTTPTransportError.new("", "401"))
|
73
72
|
expect { subject.relay_command("cmd.exe echo 'hi'") }.to raise_error(WinRM::WinRMHTTPTransportError)
|
74
73
|
expect(subject.exit_code).to eql(401)
|
75
74
|
end
|
@@ -16,8 +16,8 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
19
|
+
require "spec_helper"
|
20
|
+
require "dummy_winrm_connection"
|
21
21
|
|
22
22
|
Chef::Knife::Winrm.load_deps
|
23
23
|
|
@@ -43,7 +43,7 @@ describe Chef::Knife::Winrm do
|
|
43
43
|
context "when there are some hosts found but they do not have an attribute to connect with" do
|
44
44
|
before do
|
45
45
|
@knife.config[:manual] = false
|
46
|
-
@knife.config[:winrm_password] =
|
46
|
+
@knife.config[:winrm_password] = "P@ssw0rd!"
|
47
47
|
allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
|
48
48
|
@node_foo.automatic_attrs[:fqdn] = nil
|
49
49
|
@node_bar.automatic_attrs[:fqdn] = nil
|
@@ -61,7 +61,7 @@ describe Chef::Knife::Winrm do
|
|
61
61
|
context "when there are nested attributes" do
|
62
62
|
before do
|
63
63
|
@knife.config[:manual] = false
|
64
|
-
@knife.config[:winrm_password] =
|
64
|
+
@knife.config[:winrm_password] = "P@ssw0rd!"
|
65
65
|
allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
|
66
66
|
allow(Chef::Search::Query).to receive(:new).and_return(@query)
|
67
67
|
end
|
@@ -75,28 +75,28 @@ describe Chef::Knife::Winrm do
|
|
75
75
|
end
|
76
76
|
|
77
77
|
describe "#configure_session" do
|
78
|
-
let(:winrm_user) {
|
79
|
-
let(:transport) {
|
80
|
-
let(:password) {
|
81
|
-
let(:protocol) {
|
78
|
+
let(:winrm_user) { "testuser" }
|
79
|
+
let(:transport) { "plaintext" }
|
80
|
+
let(:password) { "testpassword" }
|
81
|
+
let(:protocol) { "basic" }
|
82
82
|
let(:knife_args) do
|
83
83
|
[
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
84
|
+
"-m", "localhost",
|
85
|
+
"-x", winrm_user,
|
86
|
+
"-P", password,
|
87
|
+
"-w", transport,
|
88
|
+
"--winrm-authentication-protocol", protocol,
|
89
|
+
"echo helloworld"
|
90
90
|
]
|
91
91
|
end
|
92
|
-
let(:winrm_session) { double(
|
92
|
+
let(:winrm_session) { double("winrm_session") }
|
93
93
|
let(:winrm_connection) { Dummy::Connection.new }
|
94
94
|
|
95
95
|
subject { Chef::Knife::Winrm.new(knife_args) }
|
96
96
|
|
97
97
|
context "when configuring the WinRM user name" do
|
98
98
|
context "when basic auth is used" do
|
99
|
-
let(:protocol) {
|
99
|
+
let(:protocol) { "basic" }
|
100
100
|
|
101
101
|
it "passes user name as given in options" do
|
102
102
|
expect(Chef::Knife::WinrmSession).to receive(:new) do |opts|
|
@@ -107,7 +107,7 @@ describe Chef::Knife::Winrm do
|
|
107
107
|
end
|
108
108
|
|
109
109
|
context "when negotiate auth is used" do
|
110
|
-
let(:protocol) {
|
110
|
+
let(:protocol) { "negotiate" }
|
111
111
|
|
112
112
|
context "when user is prefixed with realm" do
|
113
113
|
let(:winrm_user) { "my_realm\\myself" }
|
@@ -153,14 +153,14 @@ describe Chef::Knife::Winrm do
|
|
153
153
|
context "when no password is given in the options" do
|
154
154
|
let(:knife_args) do
|
155
155
|
[
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
156
|
+
"-m", "localhost",
|
157
|
+
"-x", winrm_user,
|
158
|
+
"-w", transport,
|
159
|
+
"--winrm-authentication-protocol", protocol,
|
160
|
+
"echo helloworld"
|
161
161
|
]
|
162
162
|
end
|
163
|
-
let(:prompted_password) {
|
163
|
+
let(:prompted_password) { "prompted_password" }
|
164
164
|
|
165
165
|
before do
|
166
166
|
allow(subject.ui).to receive(:ask).and_return(prompted_password)
|
@@ -177,41 +177,45 @@ describe Chef::Knife::Winrm do
|
|
177
177
|
|
178
178
|
context "when configuring the WinRM transport" do
|
179
179
|
context "kerberos option is set" do
|
180
|
-
let(:winrm_command_http) {
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
180
|
+
let(:winrm_command_http) {
|
181
|
+
Chef::Knife::Winrm.new([
|
182
|
+
"-m", "localhost",
|
183
|
+
"-x", "testuser",
|
184
|
+
"-P", "testpassword",
|
185
|
+
"--winrm-authentication-protocol", "basic",
|
186
|
+
"--kerberos-realm", "realm",
|
187
|
+
"echo helloworld"
|
188
|
+
])
|
189
|
+
}
|
188
190
|
|
189
191
|
it "sets the transport to kerberos" do
|
190
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
192
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(transport: :kerberos)).and_return(winrm_connection)
|
191
193
|
winrm_command_http.configure_chef
|
192
194
|
winrm_command_http.configure_session
|
193
195
|
end
|
194
196
|
end
|
195
197
|
|
196
198
|
context "kerberos option is set but nil" do
|
197
|
-
let(:winrm_command_http) {
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
199
|
+
let(:winrm_command_http) {
|
200
|
+
Chef::Knife::Winrm.new([
|
201
|
+
"-m", "localhost",
|
202
|
+
"-x", "testuser",
|
203
|
+
"-P", "testpassword",
|
204
|
+
"--winrm-authentication-protocol", "basic",
|
205
|
+
"echo helloworld"
|
206
|
+
])
|
207
|
+
}
|
204
208
|
|
205
209
|
it "sets the transport to plaintext" do
|
206
210
|
winrm_command_http.config[:kerberos_realm] = nil
|
207
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
211
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(transport: :plaintext)).and_return(winrm_connection)
|
208
212
|
winrm_command_http.configure_chef
|
209
213
|
winrm_command_http.configure_session
|
210
214
|
end
|
211
215
|
end
|
212
216
|
|
213
217
|
context "on windows workstations" do
|
214
|
-
let(:protocol) {
|
218
|
+
let(:protocol) { "negotiate" }
|
215
219
|
|
216
220
|
before do
|
217
221
|
allow(Chef::Platform).to receive(:windows?).and_return(true)
|
@@ -230,88 +234,88 @@ describe Chef::Knife::Winrm do
|
|
230
234
|
allow(Chef::Platform).to receive(:windows?).and_return(false)
|
231
235
|
end
|
232
236
|
|
233
|
-
let(:winrm_command_http) { Chef::Knife::Winrm.new([
|
237
|
+
let(:winrm_command_http) { Chef::Knife::Winrm.new(["-m", "localhost", "-x", "testuser", "-P", "testpassword", "-w", "plaintext", "--winrm-authentication-protocol", "basic", "echo helloworld"]) }
|
234
238
|
|
235
239
|
it "defaults to the http uri scheme" do
|
236
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
237
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
240
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(transport: :plaintext)).and_call_original
|
241
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(endpoint: "http://localhost:5985/wsman")).and_return(winrm_connection)
|
238
242
|
winrm_command_http.configure_chef
|
239
243
|
winrm_command_http.configure_session
|
240
244
|
end
|
241
245
|
|
242
246
|
it "sets the operation timeout and verifes default" do
|
243
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
244
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
247
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(operation_timeout: 1800)).and_call_original
|
248
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(operation_timeout: 1800)).and_return(winrm_connection)
|
245
249
|
winrm_command_http.configure_chef
|
246
250
|
winrm_command_http.configure_session
|
247
251
|
end
|
248
252
|
|
249
253
|
it "sets the user specified winrm port" do
|
250
|
-
Chef::Config[:knife] = {winrm_port: "5988"}
|
251
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
252
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
254
|
+
Chef::Config[:knife] = { winrm_port: "5988" }
|
255
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(transport: :plaintext)).and_call_original
|
256
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(transport: :plaintext)).and_return(winrm_connection)
|
253
257
|
winrm_command_http.configure_chef
|
254
258
|
winrm_command_http.configure_session
|
255
259
|
end
|
256
260
|
|
257
|
-
let(:winrm_command_timeout) { Chef::Knife::Winrm.new([
|
261
|
+
let(:winrm_command_timeout) { Chef::Knife::Winrm.new(["-m", "localhost", "-x", "testuser", "-P", "testpassword", "--winrm-authentication-protocol", "basic", "--session-timeout", "10", "echo helloworld"]) }
|
258
262
|
|
259
263
|
it "sets operation timeout and verify 10 Minute timeout" do
|
260
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
261
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
264
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(operation_timeout: 600)).and_call_original
|
265
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(operation_timeout: 600)).and_return(winrm_connection)
|
262
266
|
winrm_command_timeout.configure_chef
|
263
267
|
winrm_command_timeout.configure_session
|
264
268
|
end
|
265
269
|
|
266
|
-
let(:winrm_command_https) { Chef::Knife::Winrm.new([
|
270
|
+
let(:winrm_command_https) { Chef::Knife::Winrm.new(["-m", "localhost", "-x", "testuser", "-P", "testpassword", "--winrm-transport", "ssl", "echo helloworld"]) }
|
267
271
|
|
268
272
|
it "uses the https uri scheme if the ssl transport is specified" do
|
269
|
-
Chef::Config[:knife] = {:
|
270
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
271
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
273
|
+
Chef::Config[:knife] = { winrm_transport: "ssl" }
|
274
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(transport: :ssl)).and_call_original
|
275
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(endpoint: "https://localhost:5986/wsman")).and_return(winrm_connection)
|
272
276
|
winrm_command_https.configure_chef
|
273
277
|
winrm_command_https.configure_session
|
274
278
|
end
|
275
279
|
|
276
280
|
it "uses the winrm port '5986' by default for ssl transport" do
|
277
|
-
Chef::Config[:knife] = {:
|
278
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
279
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
281
|
+
Chef::Config[:knife] = { winrm_transport: "ssl" }
|
282
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(transport: :ssl)).and_call_original
|
283
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(endpoint: "https://localhost:5986/wsman")).and_return(winrm_connection)
|
280
284
|
winrm_command_https.configure_chef
|
281
285
|
winrm_command_https.configure_session
|
282
286
|
end
|
283
287
|
|
284
288
|
it "defaults to validating the server when the ssl transport is used" do
|
285
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
286
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
289
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(transport: :ssl)).and_call_original
|
290
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(no_ssl_peer_verification: false)).and_return(winrm_connection)
|
287
291
|
winrm_command_https.configure_chef
|
288
292
|
winrm_command_https.configure_session
|
289
293
|
end
|
290
294
|
|
291
|
-
let(:winrm_command_verify_peer) { Chef::Knife::Winrm.new([
|
295
|
+
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"]) }
|
292
296
|
|
293
297
|
it "validates the server when the ssl transport is used and the :winrm_ssl_verify_mode option is not configured to :verify_none" do
|
294
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
295
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
298
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(transport: :ssl)).and_call_original
|
299
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(no_ssl_peer_verification: false)).and_return(winrm_connection)
|
296
300
|
winrm_command_verify_peer.configure_chef
|
297
301
|
winrm_command_verify_peer.configure_session
|
298
302
|
end
|
299
303
|
|
300
304
|
context "when setting verify_none" do
|
301
|
-
let(:transport) {
|
305
|
+
let(:transport) { "ssl" }
|
302
306
|
|
303
|
-
before { knife_args <<
|
307
|
+
before { knife_args << "--winrm-ssl-verify-mode" << "verify_none" }
|
304
308
|
|
305
309
|
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
|
306
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
307
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
310
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(transport: :ssl)).and_call_original
|
311
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(no_ssl_peer_verification: true)).and_return(winrm_connection)
|
308
312
|
subject.configure_chef
|
309
313
|
subject.configure_session
|
310
314
|
end
|
311
315
|
|
312
316
|
it "prints warning output when the :winrm_ssl_verify_mode set to :verify_none to disable server validation" do
|
313
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
314
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
317
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(transport: :ssl)).and_call_original
|
318
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(no_ssl_peer_verification: true)).and_return(winrm_connection)
|
315
319
|
expect(subject).to receive(:warn_no_ssl_peer_verification)
|
316
320
|
|
317
321
|
subject.configure_chef
|
@@ -319,10 +323,10 @@ describe Chef::Knife::Winrm do
|
|
319
323
|
end
|
320
324
|
|
321
325
|
context "when transport is plaintext" do
|
322
|
-
let(:transport) {
|
326
|
+
let(:transport) { "plaintext" }
|
323
327
|
|
324
328
|
it "does not print warning re ssl server validation" do
|
325
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
329
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(transport: :plaintext)).and_call_original
|
326
330
|
expect(WinRM::Connection).to receive(:new).and_return(winrm_connection)
|
327
331
|
expect(subject).to_not receive(:warn_no_ssl_peer_verification)
|
328
332
|
|
@@ -332,11 +336,11 @@ describe Chef::Knife::Winrm do
|
|
332
336
|
end
|
333
337
|
end
|
334
338
|
|
335
|
-
let(:winrm_command_ca_trust) { Chef::Knife::Winrm.new([
|
339
|
+
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"]) }
|
336
340
|
|
337
341
|
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
|
338
|
-
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(:
|
339
|
-
expect(WinRM::Connection).to receive(:new).with(hash_including(:
|
342
|
+
expect(Chef::Knife::WinrmSession).to receive(:new).with(hash_including(transport: :ssl)).and_call_original
|
343
|
+
expect(WinRM::Connection).to receive(:new).with(hash_including(no_ssl_peer_verification: false)).and_return(winrm_connection)
|
340
344
|
winrm_command_ca_trust.configure_chef
|
341
345
|
winrm_command_ca_trust.configure_session
|
342
346
|
end
|
@@ -351,15 +355,15 @@ describe Chef::Knife::Winrm do
|
|
351
355
|
password: "testpassword",
|
352
356
|
port: "5985",
|
353
357
|
transport: :plaintext,
|
354
|
-
host: "localhost"
|
358
|
+
host: "localhost",
|
355
359
|
}
|
356
360
|
end
|
357
361
|
let(:session) { Chef::Knife::WinrmSession.new(session_opts) }
|
358
362
|
|
359
363
|
before(:each) do
|
360
364
|
allow(Chef::Knife::WinrmSession).to receive(:new).and_return(session)
|
361
|
-
Chef::Config[:knife] = {:
|
362
|
-
@winrm = Chef::Knife::Winrm.new([
|
365
|
+
Chef::Config[:knife] = { winrm_transport: "plaintext" }
|
366
|
+
@winrm = Chef::Knife::Winrm.new(["-m", "localhost", "-x", "testuser", "-P", "testpassword", "--winrm-authentication-protocol", "basic", "echo helloworld"])
|
363
367
|
end
|
364
368
|
|
365
369
|
it "returns with 0 if the command succeeds" do
|
@@ -383,7 +387,7 @@ describe Chef::Knife::Winrm do
|
|
383
387
|
it "exits with non-zero status if the command fails and returns config is set to 0" do
|
384
388
|
command_status = 1
|
385
389
|
@winrm.config[:returns] = "0,53"
|
386
|
-
Chef::Config[:knife][:returns] = [0,53]
|
390
|
+
Chef::Config[:knife][:returns] = [0, 53]
|
387
391
|
allow(@winrm).to receive(:relay_winrm_command).and_return(command_status)
|
388
392
|
allow(@winrm.ui).to receive(:error)
|
389
393
|
allow(session).to receive(:exit_code).and_return(command_status)
|
@@ -392,31 +396,31 @@ describe Chef::Knife::Winrm do
|
|
392
396
|
|
393
397
|
it "exits with a zero status if the command returns an expected non-zero status" do
|
394
398
|
command_status = 53
|
395
|
-
Chef::Config[:knife][:returns] = [0,53]
|
399
|
+
Chef::Config[:knife][:returns] = [0, 53]
|
396
400
|
allow(@winrm).to receive(:relay_winrm_command).and_return(command_status)
|
397
|
-
allow(session).to receive(:exit_codes).and_return({"thishost" => command_status})
|
401
|
+
allow(session).to receive(:exit_codes).and_return({ "thishost" => command_status })
|
398
402
|
exit_code = @winrm.run
|
399
403
|
expect(exit_code).to be_zero
|
400
404
|
end
|
401
405
|
|
402
406
|
it "exits with a zero status if the command returns an expected non-zero status" do
|
403
407
|
command_status = 53
|
404
|
-
@winrm.config[:returns] =
|
408
|
+
@winrm.config[:returns] = "0,53"
|
405
409
|
allow(@winrm).to receive(:relay_winrm_command).and_return(command_status)
|
406
|
-
allow(session).to receive(:exit_codes).and_return({"thishost" => command_status})
|
410
|
+
allow(session).to receive(:exit_codes).and_return({ "thishost" => command_status })
|
407
411
|
exit_code = @winrm.run
|
408
412
|
expect(exit_code).to be_zero
|
409
413
|
end
|
410
414
|
|
411
415
|
it "exits with 100 and no hint if command execution raises an exception other than 401" do
|
412
|
-
allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new(
|
416
|
+
allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new("", "500"))
|
413
417
|
allow(@winrm.ui).to receive(:error)
|
414
418
|
expect(@winrm.ui).to_not receive(:info)
|
415
419
|
expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(100) }
|
416
420
|
end
|
417
421
|
|
418
422
|
it "exits with 100 if command execution raises a 401" do
|
419
|
-
allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new(
|
423
|
+
allow(@winrm).to receive(:relay_winrm_command).and_raise(WinRM::WinRMHTTPTransportError.new("", "401"))
|
420
424
|
allow(@winrm.ui).to receive(:info)
|
421
425
|
allow(@winrm.ui).to receive(:error)
|
422
426
|
expect { @winrm.run_with_pretty_exceptions }.to raise_error(SystemExit) { |e| expect(e.status).to eq(100) }
|
@@ -436,7 +440,7 @@ describe Chef::Knife::Winrm do
|
|
436
440
|
it "prints a hint on failure for basic authentication" do
|
437
441
|
@winrm.config[:winrm_authentication_protocol] = "basic"
|
438
442
|
@winrm.config[:winrm_transport] = "plaintext"
|
439
|
-
allow(session).to receive(:relay_command).and_raise(WinRM::WinRMHTTPTransportError.new(
|
443
|
+
allow(session).to receive(:relay_command).and_raise(WinRM::WinRMHTTPTransportError.new("", "401"))
|
440
444
|
allow(@winrm.ui).to receive(:error)
|
441
445
|
allow(@winrm.ui).to receive(:info)
|
442
446
|
expect(@winrm.ui).to receive(:info).with(Chef::Knife::Winrm::FAILED_BASIC_HINT)
|
@@ -445,7 +449,7 @@ describe Chef::Knife::Winrm do
|
|
445
449
|
|
446
450
|
context "when winrm_authentication_protocol specified" do
|
447
451
|
before do
|
448
|
-
Chef::Config[:knife] = {:
|
452
|
+
Chef::Config[:knife] = { winrm_transport: "plaintext" }
|
449
453
|
allow(@winrm).to receive(:relay_winrm_command).and_return(0)
|
450
454
|
end
|
451
455
|
|