knife-windows 3.0.6 → 3.0.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|