knife-windows 1.0.0.rc.1 → 1.0.0.rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -5
  3. data/.travis.yml +20 -20
  4. data/CHANGELOG.md +75 -74
  5. data/DOC_CHANGES.md +323 -323
  6. data/Gemfile +12 -12
  7. data/LICENSE +201 -201
  8. data/README.md +393 -292
  9. data/RELEASE_NOTES.md +79 -74
  10. data/Rakefile +21 -16
  11. data/appveyor.yml +42 -42
  12. data/ci.gemfile +15 -15
  13. data/features/knife_help.feature +20 -20
  14. data/features/support/env.rb +5 -5
  15. data/knife-windows.gemspec +28 -28
  16. data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +247 -241
  17. data/lib/chef/knife/bootstrap_windows_base.rb +388 -368
  18. data/lib/chef/knife/bootstrap_windows_ssh.rb +110 -110
  19. data/lib/chef/knife/bootstrap_windows_winrm.rb +102 -113
  20. data/lib/chef/knife/core/windows_bootstrap_context.rb +361 -362
  21. data/lib/chef/knife/knife_windows_base.rb +33 -0
  22. data/lib/chef/knife/windows_cert_generate.rb +155 -155
  23. data/lib/chef/knife/windows_cert_install.rb +68 -68
  24. data/lib/chef/knife/windows_helper.rb +36 -36
  25. data/lib/chef/knife/windows_listener_create.rb +107 -107
  26. data/lib/chef/knife/winrm.rb +212 -191
  27. data/lib/chef/knife/winrm_base.rb +118 -125
  28. data/lib/chef/knife/winrm_knife_base.rb +218 -201
  29. data/lib/chef/knife/winrm_session.rb +80 -71
  30. data/lib/chef/knife/winrm_shared_options.rb +47 -47
  31. data/lib/chef/knife/wsman_endpoint.rb +44 -44
  32. data/lib/chef/knife/wsman_test.rb +96 -96
  33. data/lib/knife-windows/path_helper.rb +234 -234
  34. data/lib/knife-windows/version.rb +6 -6
  35. data/spec/assets/win_template_rendered_with_bootstrap_install_command.txt +217 -0
  36. data/spec/assets/win_template_rendered_without_bootstrap_install_command.txt +329 -0
  37. data/spec/assets/win_template_unrendered.txt +246 -0
  38. data/spec/functional/bootstrap_download_spec.rb +216 -140
  39. data/spec/spec_helper.rb +87 -72
  40. data/spec/unit/knife/bootstrap_options_spec.rb +146 -146
  41. data/spec/unit/knife/bootstrap_template_spec.rb +92 -92
  42. data/spec/unit/knife/bootstrap_windows_winrm_spec.rb +240 -161
  43. data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +151 -101
  44. data/spec/unit/knife/windows_cert_generate_spec.rb +90 -90
  45. data/spec/unit/knife/windows_cert_install_spec.rb +51 -51
  46. data/spec/unit/knife/windows_listener_create_spec.rb +76 -76
  47. data/spec/unit/knife/winrm_session_spec.rb +55 -46
  48. data/spec/unit/knife/winrm_spec.rb +504 -376
  49. data/spec/unit/knife/wsman_test_spec.rb +175 -175
  50. metadata +28 -8
@@ -1,125 +1,118 @@
1
- #
2
- # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
- # Copyright:: Copyright (c) 2011 Opscode, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'chef/knife'
20
- require 'chef/encrypted_data_bag_item'
21
- require 'kconv'
22
-
23
- class Chef
24
- class Knife
25
- module WinrmBase
26
-
27
- # It includes supported WinRM authentication protocol.
28
- WINRM_AUTH_PROTOCOL_LIST ||= %w{basic negotiate kerberos}
29
-
30
- # :nodoc:
31
- # Would prefer to do this in a rational way, but can't be done b/c of
32
- # Mixlib::CLI's design :(
33
- def self.included(includer)
34
- includer.class_eval do
35
-
36
- deps do
37
- require 'readline'
38
- require 'chef/json_compat'
39
- end
40
-
41
- option :winrm_user,
42
- :short => "-x USERNAME",
43
- :long => "--winrm-user USERNAME",
44
- :description => "The WinRM username",
45
- :default => "Administrator",
46
- :proc => Proc.new { |key| Chef::Config[:knife][:winrm_user] = key }
47
-
48
- option :winrm_password,
49
- :short => "-P PASSWORD",
50
- :long => "--winrm-password PASSWORD",
51
- :description => "The WinRM password",
52
- :proc => Proc.new { |key| Chef::Config[:knife][:winrm_password] = key }
53
-
54
- option :winrm_transport,
55
- :short => "-t TRANSPORT",
56
- :long => "--winrm-transport TRANSPORT",
57
- :description => "The WinRM transport type. valid choices are [ssl, plaintext]",
58
- :default => 'plaintext',
59
- :proc => Proc.new { |transport| Chef::Config[:knife][:winrm_port] = '5986' if transport == 'ssl'
60
- Chef::Config[:knife][:winrm_transport] = transport }
61
-
62
- option :winrm_port,
63
- :short => "-p PORT",
64
- :long => "--winrm-port PORT",
65
- :description => "The WinRM port, by default this is '5985' for 'plaintext' and '5986' for 'ssl' winrm transport",
66
- :default => '5985',
67
- :proc => Proc.new { |key| Chef::Config[:knife][:winrm_port] = key }
68
-
69
- option :identity_file,
70
- :short => "-i IDENTITY_FILE",
71
- :long => "--identity-file IDENTITY_FILE",
72
- :description => "The SSH identity file used for authentication"
73
-
74
- option :kerberos_keytab_file,
75
- :short => "-T KEYTAB_FILE",
76
- :long => "--keytab-file KEYTAB_FILE",
77
- :description => "The Kerberos keytab file used for authentication",
78
- :proc => Proc.new { |keytab| Chef::Config[:knife][:kerberos_keytab_file] = keytab }
79
-
80
- option :kerberos_realm,
81
- :short => "-R KERBEROS_REALM",
82
- :long => "--kerberos-realm KERBEROS_REALM",
83
- :description => "The Kerberos realm used for authentication",
84
- :proc => Proc.new { |realm| Chef::Config[:knife][:kerberos_realm] = realm }
85
-
86
- option :kerberos_service,
87
- :short => "-S KERBEROS_SERVICE",
88
- :long => "--kerberos-service KERBEROS_SERVICE",
89
- :description => "The Kerberos service used for authentication",
90
- :proc => Proc.new { |service| Chef::Config[:knife][:kerberos_service] = service }
91
-
92
- option :ca_trust_file,
93
- :short => "-f CA_TRUST_FILE",
94
- :long => "--ca-trust-file CA_TRUST_FILE",
95
- :description => "The Certificate Authority (CA) trust file used for SSL transport",
96
- :proc => Proc.new { |trust| Chef::Config[:knife][:ca_trust_file] = trust }
97
-
98
- option :winrm_ssl_verify_mode,
99
- :long => "--winrm-ssl-verify-mode SSL_VERIFY_MODE",
100
- :description => "The WinRM peer verification mode. Valid choices are [verify_peer, verify_none]",
101
- :default => :verify_peer,
102
- :proc => Proc.new { |verify_mode| verify_mode.to_sym }
103
-
104
- option :winrm_authentication_protocol,
105
- :long => "--winrm-authentication-protocol AUTHENTICATION_PROTOCOL",
106
- :description => "The authentication protocol used during WinRM communication. The supported protocols are #{WINRM_AUTH_PROTOCOL_LIST.join(',')}. Default is 'negotiate'.",
107
- :default => "negotiate",
108
- :proc => Proc.new { |protocol| Chef::Config[:knife][:winrm_authentication_protocol] = protocol }
109
-
110
- option :session_timeout,
111
- :long => "--session-timeout Minutes",
112
- :description => "The timeout for the client for the maximum length of the WinRM session",
113
- :default => 30
114
- end
115
- end
116
-
117
- def locate_config_value(key)
118
- key = key.to_sym
119
- value = config[key] || Chef::Config[:knife][key] || default_config[key]
120
- Chef::Log.debug("Looking for key #{key} and found value #{value}")
121
- value
122
- end
123
- end
124
- end
125
- end
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
+ # Copyright:: Copyright (c) 2011 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/knife'
20
+ require 'chef/encrypted_data_bag_item'
21
+ require 'kconv'
22
+
23
+ class Chef
24
+ class Knife
25
+ module WinrmBase
26
+
27
+ # It includes supported WinRM authentication protocol.
28
+ WINRM_AUTH_PROTOCOL_LIST ||= %w{basic negotiate kerberos}
29
+
30
+ # :nodoc:
31
+ # Would prefer to do this in a rational way, but can't be done b/c of
32
+ # Mixlib::CLI's design :(
33
+ def self.included(includer)
34
+ includer.class_eval do
35
+
36
+ deps do
37
+ require 'readline'
38
+ require 'chef/json_compat'
39
+ end
40
+
41
+ option :winrm_user,
42
+ :short => "-x USERNAME",
43
+ :long => "--winrm-user USERNAME",
44
+ :description => "The WinRM username",
45
+ :default => "Administrator",
46
+ :proc => Proc.new { |key| Chef::Config[:knife][:winrm_user] = key }
47
+
48
+ option :winrm_password,
49
+ :short => "-P PASSWORD",
50
+ :long => "--winrm-password PASSWORD",
51
+ :description => "The WinRM password",
52
+ :proc => Proc.new { |key| Chef::Config[:knife][:winrm_password] = key }
53
+
54
+ option :winrm_transport,
55
+ :short => "-t TRANSPORT",
56
+ :long => "--winrm-transport TRANSPORT",
57
+ :description => "The WinRM transport type. valid choices are [ssl, plaintext]",
58
+ :default => 'plaintext',
59
+ :proc => Proc.new { |transport| Chef::Config[:knife][:winrm_port] = '5986' if transport == 'ssl'
60
+ Chef::Config[:knife][:winrm_transport] = transport }
61
+
62
+ option :winrm_port,
63
+ :short => "-p PORT",
64
+ :long => "--winrm-port PORT",
65
+ :description => "The WinRM port, by default this is '5985' for 'plaintext' and '5986' for 'ssl' winrm transport",
66
+ :default => '5985',
67
+ :proc => Proc.new { |key| Chef::Config[:knife][:winrm_port] = key }
68
+
69
+ option :identity_file,
70
+ :short => "-i IDENTITY_FILE",
71
+ :long => "--identity-file IDENTITY_FILE",
72
+ :description => "The SSH identity file used for authentication"
73
+
74
+ option :kerberos_keytab_file,
75
+ :short => "-T KEYTAB_FILE",
76
+ :long => "--keytab-file KEYTAB_FILE",
77
+ :description => "The Kerberos keytab file used for authentication",
78
+ :proc => Proc.new { |keytab| Chef::Config[:knife][:kerberos_keytab_file] = keytab }
79
+
80
+ option :kerberos_realm,
81
+ :short => "-R KERBEROS_REALM",
82
+ :long => "--kerberos-realm KERBEROS_REALM",
83
+ :description => "The Kerberos realm used for authentication",
84
+ :proc => Proc.new { |realm| Chef::Config[:knife][:kerberos_realm] = realm }
85
+
86
+ option :kerberos_service,
87
+ :short => "-S KERBEROS_SERVICE",
88
+ :long => "--kerberos-service KERBEROS_SERVICE",
89
+ :description => "The Kerberos service used for authentication",
90
+ :proc => Proc.new { |service| Chef::Config[:knife][:kerberos_service] = service }
91
+
92
+ option :ca_trust_file,
93
+ :short => "-f CA_TRUST_FILE",
94
+ :long => "--ca-trust-file CA_TRUST_FILE",
95
+ :description => "The Certificate Authority (CA) trust file used for SSL transport",
96
+ :proc => Proc.new { |trust| Chef::Config[:knife][:ca_trust_file] = trust }
97
+
98
+ option :winrm_ssl_verify_mode,
99
+ :long => "--winrm-ssl-verify-mode SSL_VERIFY_MODE",
100
+ :description => "The WinRM peer verification mode. Valid choices are [verify_peer, verify_none]",
101
+ :default => :verify_peer,
102
+ :proc => Proc.new { |verify_mode| verify_mode.to_sym }
103
+
104
+ option :winrm_authentication_protocol,
105
+ :long => "--winrm-authentication-protocol AUTHENTICATION_PROTOCOL",
106
+ :description => "The authentication protocol used during WinRM communication. The supported protocols are #{WINRM_AUTH_PROTOCOL_LIST.join(',')}. Default is 'negotiate'.",
107
+ :default => "negotiate",
108
+ :proc => Proc.new { |protocol| Chef::Config[:knife][:winrm_authentication_protocol] = protocol }
109
+
110
+ option :session_timeout,
111
+ :long => "--session-timeout Minutes",
112
+ :description => "The timeout for the client for the maximum length of the WinRM session",
113
+ :default => 30
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -1,201 +1,218 @@
1
- #
2
- # Author:: Steven Murawski (<smurawski@chef.io)
3
- # Copyright:: Copyright (c) 2015 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
-
20
- require 'chef/knife'
21
- require 'chef/knife/winrm_base'
22
- require 'chef/knife/winrm_shared_options'
23
-
24
- class Chef
25
- class Knife
26
- module WinrmCommandSharedFunctions
27
- def self.included(includer)
28
- includer.class_eval do
29
-
30
- @@ssl_warning_given = false
31
-
32
- include Chef::Knife::WinrmBase
33
- include Chef::Knife::WinrmSharedOptions
34
-
35
- #Overrides Chef::Knife#configure_session, as that code is tied to the SSH implementation
36
- #Tracked by Issue # 3042 / https://github.com/chef/chef/issues/3042
37
- def configure_session
38
- resolve_session_options
39
- resolve_target_nodes
40
- session_from_list
41
- end
42
-
43
- def resolve_target_nodes
44
- @list = case config[:manual]
45
- when true
46
- @name_args[0].split(" ")
47
- when false
48
- r = Array.new
49
- q = Chef::Search::Query.new
50
- @action_nodes = q.search(:node, @name_args[0])[0]
51
- @action_nodes.each do |item|
52
- i = extract_nested_value(item, config[:attribute])
53
- r.push(i) unless i.nil?
54
- end
55
- r
56
- end
57
- if @list.length == 0
58
- if @action_nodes.length == 0
59
- ui.fatal("No nodes returned from search!")
60
- else
61
- ui.fatal("#{@action_nodes.length} #{@action_nodes.length > 1 ? "nodes":"node"} found, " +
62
- "but does not have the required attribute (#{config[:attribute]}) to establish the connection. " +
63
- "Try setting another attribute to open the connection using --attribute.")
64
- end
65
- exit 10
66
- end
67
- end
68
-
69
- def validate_password
70
- if @session_opts[:user] and (not @session_opts[:password])
71
- @session_opts[:password] = Chef::Config[:knife][:winrm_password] = config[:winrm_password] = get_password
72
- end
73
- end
74
-
75
- private
76
-
77
- def session_from_list
78
- @list.each do |item|
79
- Chef::Log.debug("Adding #{item}")
80
- @session_opts[:host] = item
81
- create_winrm_session(@session_opts)
82
- end
83
- end
84
-
85
- def create_winrm_session(options={})
86
- session = Chef::Knife::WinrmSession.new(options)
87
- @winrm_sessions ||= []
88
- @winrm_sessions.push(session)
89
- end
90
-
91
- def resolve_session_options
92
- resolve_winrm_basic_options
93
- resolve_winrm_auth_settings
94
- resolve_winrm_kerberos_options
95
- resolve_winrm_transport_options
96
- resolve_winrm_ssl_options
97
- end
98
-
99
- def resolve_winrm_basic_options
100
- @session_opts = {}
101
- @session_opts[:user] = locate_config_value(:winrm_user)
102
- @session_opts[:password] = locate_config_value(:winrm_password)
103
- @session_opts[:port] = locate_config_value(:winrm_port)
104
-
105
- #30 min (Default) OperationTimeout for long bootstraps fix for KNIFE_WINDOWS-8
106
- @session_opts[:operation_timeout] = locate_config_value(:session_timeout).to_i * 60 if locate_config_value(:session_timeout)
107
- end
108
-
109
- def resolve_winrm_kerberos_options
110
- if config.keys.any? {|k| k.to_s =~ /kerberos/ }
111
- @session_opts[:transport] = :kerberos
112
- @session_opts[:keytab] = locate_config_value(:kerberos_keytab_file) if locate_config_value(:kerberos_keytab_file)
113
- @session_opts[:realm] = locate_config_value(:kerberos_realm) if locate_config_value(:kerberos_realm)
114
- @session_opts[:service] = locate_config_value(:kerberos_service) if locate_config_value(:kerberos_service)
115
- end
116
- end
117
-
118
- def resolve_winrm_transport_options
119
- @session_opts[:disable_sspi] = true
120
- @session_opts[:transport] = locate_config_value(:winrm_transport).to_sym unless @session_opts[:transport] == :kerberos
121
- if negotiate_auth? && @session_opts[:transport] == :ssl
122
- Chef::Log.debug("Trying WinRM communication with negotiate authentication and :ssl transport")
123
- elsif use_windows_native_auth?
124
- load_windows_specific_gems
125
- @session_opts[:transport] = :sspinegotiate
126
- @session_opts[:disable_sspi] = false
127
- elsif negotiate_auth? && !Chef::Platform.windows?
128
- ui.warn "\nUsing '--winrm-authentication-protocol negotiate' with '--winrm-transport plaintext' is only supported when this tool is invoked from a Windows system."
129
- ui.warn "Switch to either '--winrm-transport ssl' or '--winrm-authentication-protocol basic'."
130
- exit 1
131
- end
132
- end
133
-
134
- def resolve_winrm_ssl_options
135
- @session_opts[:ca_trust_path] = locate_config_value(:ca_trust_file) if locate_config_value(:ca_trust_file)
136
- @session_opts[:no_ssl_peer_verification] = no_ssl_peer_verification?(@session_opts[:ca_trust_path])
137
- warn_no_ssl_peer_verification if @session_opts[:no_ssl_peer_verification]
138
- end
139
-
140
- def resolve_winrm_auth_settings
141
- winrm_auth_protocol = locate_config_value(:winrm_authentication_protocol)
142
- if ! Chef::Knife::WinrmBase::WINRM_AUTH_PROTOCOL_LIST.include?(winrm_auth_protocol)
143
- ui.error "Invalid value '#{winrm_auth_protocol}' for --winrm-authentication-protocol option."
144
- ui.info "Valid values are #{Chef::Knife::WinrmBase::WINRM_AUTH_PROTOCOL_LIST.join(",")}."
145
- exit 1
146
- end
147
-
148
- if winrm_auth_protocol == "basic"
149
- @session_opts[:basic_auth_only] = true
150
- else
151
- @session_opts[:basic_auth_only] = false
152
- end
153
- end
154
-
155
- def no_ssl_peer_verification?(ca_trust_path)
156
- ca_trust_path.nil? && (config[:winrm_ssl_verify_mode] == :verify_none)
157
- end
158
-
159
- def use_windows_native_auth?
160
- Chef::Platform.windows? && @session_opts[:transport] != :ssl && negotiate_auth?
161
- end
162
-
163
- def load_windows_specific_gems
164
- require 'winrm-s'
165
- Chef::Log.debug("Applied 'winrm-s' monkey patch and trying WinRM communication with 'sspinegotiate'")
166
- end
167
-
168
- def get_password
169
- @password ||= ui.ask("Enter your password: ") { |q| q.echo = false }
170
- end
171
-
172
- # returns true if winrm_authentication_protocol is 'negotiate'
173
- def negotiate_auth?
174
- locate_config_value(:winrm_authentication_protocol) == "negotiate"
175
- end
176
-
177
- def warn_no_ssl_peer_verification
178
- if ! @@ssl_warning_given
179
- @@ssl_warning_given = true
180
- ui.warn(<<-WARN)
181
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
182
- SSL validation of HTTPS requests for the WinRM transport is disabled. HTTPS WinRM
183
- connections are still encrypted, but knife is not able to detect forged replies
184
- or spoofing attacks.
185
-
186
- To fix this issue add an entry like this to your knife configuration file:
187
-
188
- ```
189
- # Verify all WinRM HTTPS connections (default, recommended)
190
- knife[:winrm_ssl_verify_mode] = :verify_peer
191
- ```
192
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
193
- WARN
194
- end
195
- end
196
-
197
- end
198
- end
199
- end
200
- end
201
- end
1
+ #
2
+ # Author:: Steven Murawski (<smurawski@chef.io)
3
+ # Copyright:: Copyright (c) 2015 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
+
20
+ require 'chef/knife'
21
+ require 'chef/knife/winrm_base'
22
+ require 'chef/knife/winrm_shared_options'
23
+ require 'chef/knife/knife_windows_base'
24
+
25
+ class Chef
26
+ class Knife
27
+ module WinrmCommandSharedFunctions
28
+ def self.included(includer)
29
+ includer.class_eval do
30
+
31
+ @@ssl_warning_given = false
32
+
33
+ include Chef::Knife::WinrmBase
34
+ include Chef::Knife::WinrmSharedOptions
35
+ include Chef::Knife::KnifeWindowsBase
36
+
37
+ def validate_options!
38
+ winrm_auth_protocol = locate_config_value(:winrm_authentication_protocol)
39
+
40
+ if ! Chef::Knife::WinrmBase::WINRM_AUTH_PROTOCOL_LIST.include?(winrm_auth_protocol)
41
+ ui.error "Invalid value '#{winrm_auth_protocol}' for --winrm-authentication-protocol option."
42
+ ui.info "Valid values are #{Chef::Knife::WinrmBase::WINRM_AUTH_PROTOCOL_LIST.join(",")}."
43
+ exit 1
44
+ end
45
+
46
+ if negotiate_auth? && !Chef::Platform.windows? && !(locate_config_value(:winrm_transport) == 'ssl')
47
+ ui.warn <<-eos.gsub /^\s+/, ""
48
+ You are using '--winrm-authentication-protocol negotiate' with
49
+ '--winrm-transport plaintext' on a non-Windows system which results in
50
+ unencrypted traffic. To avoid this warning and secure communication,
51
+ use '--winrm-transport ssl' instead of the plaintext transport,
52
+ or execute this command from a Windows system which enables encrypted
53
+ communication over plaintext with the negotiate authentication protocol.
54
+ eos
55
+ end
56
+
57
+ warn_no_ssl_peer_verification if resolve_no_ssl_peer_verification
58
+ end
59
+
60
+ #Overrides Chef::Knife#configure_session, as that code is tied to the SSH implementation
61
+ #Tracked by Issue # 3042 / https://github.com/chef/chef/issues/3042
62
+ def configure_session
63
+ validate_options!
64
+ resolve_session_options
65
+ resolve_target_nodes
66
+ session_from_list
67
+ end
68
+
69
+ def resolve_target_nodes
70
+ @list = case config[:manual]
71
+ when true
72
+ @name_args[0].split(" ")
73
+ when false
74
+ r = Array.new
75
+ q = Chef::Search::Query.new
76
+ @action_nodes = q.search(:node, @name_args[0])[0]
77
+ @action_nodes.each do |item|
78
+ i = extract_nested_value(item, config[:attribute])
79
+ r.push(i) unless i.nil?
80
+ end
81
+ r
82
+ end
83
+
84
+ if @list.length == 0
85
+ if @action_nodes.length == 0
86
+ ui.fatal("No nodes returned from search!")
87
+ else
88
+ ui.fatal("#{@action_nodes.length} #{@action_nodes.length > 1 ? "nodes":"node"} found, " +
89
+ "but does not have the required attribute (#{config[:attribute]}) to establish the connection. " +
90
+ "Try setting another attribute to open the connection using --attribute.")
91
+ end
92
+ exit 10
93
+ end
94
+ end
95
+
96
+ def validate_password
97
+ if @session_opts[:user] and (not @session_opts[:password])
98
+ @session_opts[:password] = Chef::Config[:knife][:winrm_password] = config[:winrm_password] = get_password
99
+ end
100
+ end
101
+
102
+ private
103
+
104
+ def session_from_list
105
+ @list.each do |item|
106
+ Chef::Log.debug("Adding #{item}")
107
+ @session_opts[:host] = item
108
+ create_winrm_session(@session_opts)
109
+ end
110
+ end
111
+
112
+ def create_winrm_session(options={})
113
+ session = Chef::Knife::WinrmSession.new(options)
114
+ @winrm_sessions ||= []
115
+ @winrm_sessions.push(session)
116
+ end
117
+
118
+ def resolve_session_options
119
+ @session_opts = {
120
+ user: resolve_winrm_user,
121
+ password: locate_config_value(:winrm_password),
122
+ port: locate_config_value(:winrm_port),
123
+ operation_timeout: resolve_winrm_session_timeout,
124
+ basic_auth_only: resolve_winrm_basic_auth,
125
+ disable_sspi: resolve_winrm_disable_sspi,
126
+ transport: resolve_winrm_transport,
127
+ no_ssl_peer_verification: resolve_no_ssl_peer_verification
128
+ }
129
+ if @session_opts[:transport] == :kerberos
130
+ @session_opts.merge!(resolve_winrm_kerberos_options)
131
+ end
132
+ @session_opts[:ca_trust_path] = locate_config_value(:ca_trust_file) if locate_config_value(:ca_trust_file)
133
+ end
134
+
135
+ def resolve_winrm_user
136
+ user = locate_config_value(:winrm_user)
137
+
138
+ # Prefixing with '.\' when using negotiate
139
+ # to auth user against local machine domain
140
+ if resolve_winrm_basic_auth ||
141
+ resolve_winrm_transport == :kerberos ||
142
+ user.include?("\\") ||
143
+ user.include?("@")
144
+ user
145
+ else
146
+ ".\\#{user}"
147
+ end
148
+ end
149
+
150
+ def resolve_winrm_session_timeout
151
+ #30 min (Default) OperationTimeout for long bootstraps fix for KNIFE_WINDOWS-8
152
+ locate_config_value(:session_timeout).to_i * 60 if locate_config_value(:session_timeout)
153
+ end
154
+
155
+ def resolve_winrm_basic_auth
156
+ locate_config_value(:winrm_authentication_protocol) == "basic"
157
+ end
158
+
159
+ def resolve_winrm_kerberos_options
160
+ kerberos_opts = {}
161
+ kerberos_opts[:keytab] = locate_config_value(:kerberos_keytab_file) if locate_config_value(:kerberos_keytab_file)
162
+ kerberos_opts[:realm] = locate_config_value(:kerberos_realm) if locate_config_value(:kerberos_realm)
163
+ kerberos_opts[:service] = locate_config_value(:kerberos_service) if locate_config_value(:kerberos_service)
164
+ kerberos_opts
165
+ end
166
+
167
+ def resolve_winrm_transport
168
+ transport = locate_config_value(:winrm_transport).to_sym
169
+ if config.any? {|k,v| k.to_s =~ /kerberos/ && !v.nil? }
170
+ transport = :kerberos
171
+ elsif Chef::Platform.windows? && transport != :ssl && negotiate_auth?
172
+ transport = :sspinegotiate
173
+ end
174
+
175
+ transport
176
+ end
177
+
178
+ def resolve_no_ssl_peer_verification
179
+ locate_config_value(:ca_trust_file).nil? && config[:winrm_ssl_verify_mode] == :verify_none && resolve_winrm_transport == :ssl
180
+ end
181
+
182
+ def resolve_winrm_disable_sspi
183
+ !Chef::Platform.windows? || resolve_winrm_transport == :ssl || !negotiate_auth?
184
+ end
185
+
186
+ def get_password
187
+ @password ||= ui.ask("Enter your password: ") { |q| q.echo = false }
188
+ end
189
+
190
+ def negotiate_auth?
191
+ locate_config_value(:winrm_authentication_protocol) == "negotiate"
192
+ end
193
+
194
+ def warn_no_ssl_peer_verification
195
+ if ! @@ssl_warning_given
196
+ @@ssl_warning_given = true
197
+ ui.warn(<<-WARN)
198
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
199
+ SSL validation of HTTPS requests for the WinRM transport is disabled. HTTPS WinRM
200
+ connections are still encrypted, but knife is not able to detect forged replies
201
+ or spoofing attacks.
202
+
203
+ To fix this issue add an entry like this to your knife configuration file:
204
+
205
+ ```
206
+ # Verify all WinRM HTTPS connections (default, recommended)
207
+ knife[:winrm_ssl_verify_mode] = :verify_peer
208
+ ```
209
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
210
+ WARN
211
+ end
212
+ end
213
+
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end