chef 11.12.0.alpha.1 → 11.12.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef/api_client/registration.rb +46 -9
- data/lib/chef/application.rb +1 -0
- data/lib/chef/application/client.rb +25 -24
- data/lib/chef/client.rb +34 -0
- data/lib/chef/config.rb +11 -0
- data/lib/chef/cookbook/chefignore.rb +10 -2
- data/lib/chef/cookbook/metadata.rb +31 -3
- data/lib/chef/cookbook/synchronizer.rb +2 -2
- data/lib/chef/cookbook/syntax_check.rb +4 -4
- data/lib/chef/encrypted_data_bag_item.rb +37 -1
- data/lib/chef/exceptions.rb +1 -0
- data/lib/chef/guard_interpreter/default_guard_interpreter.rb +42 -0
- data/lib/chef/guard_interpreter/resource_guard_interpreter.rb +122 -0
- data/lib/chef/http.rb +0 -1
- data/lib/chef/http/decompressor.rb +7 -4
- data/lib/chef/http/simple.rb +5 -0
- data/lib/chef/http/validate_content_length.rb +28 -12
- data/lib/chef/knife.rb +1 -0
- data/lib/chef/knife/client_bulk_delete.rb +48 -9
- data/lib/chef/knife/client_delete.rb +4 -4
- data/lib/chef/knife/cookbook_bulk_delete.rb +1 -1
- data/lib/chef/knife/cookbook_upload.rb +17 -7
- data/lib/chef/knife/core/bootstrap_context.rb +1 -1
- data/lib/chef/knife/core/ui.rb +42 -5
- data/lib/chef/knife/node_run_list_add.rb +31 -2
- data/lib/chef/knife/ssh.rb +44 -31
- data/lib/chef/knife/ssl_check.rb +213 -0
- data/lib/chef/knife/ssl_fetch.rb +145 -0
- data/lib/chef/mixin/deep_merge.rb +13 -5
- data/lib/chef/mixin/shell_out.rb +9 -3
- data/lib/chef/node.rb +23 -4
- data/lib/chef/node/immutable_collections.rb +32 -0
- data/lib/chef/platform/provider_mapping.rb +21 -18
- data/lib/chef/platform/query_helpers.rb +10 -2
- data/lib/chef/policy_builder/expand_node_object.rb +3 -6
- data/lib/chef/provider/cron.rb +25 -3
- data/lib/chef/provider/mount/mount.rb +1 -1
- data/lib/chef/provider/package/dpkg.rb +2 -1
- data/lib/chef/provider/package/windows.rb +80 -0
- data/lib/chef/provider/package/windows/msi.rb +69 -0
- data/lib/chef/provider/powershell_script.rb +19 -6
- data/lib/chef/provider/service/solaris.rb +11 -7
- data/lib/chef/resource.rb +18 -5
- data/lib/chef/resource/conditional.rb +20 -7
- data/lib/chef/resource/cron.rb +18 -2
- data/lib/chef/resource/execute.rb +0 -2
- data/lib/chef/resource/powershell_script.rb +23 -1
- data/lib/chef/resource/script.rb +25 -0
- data/lib/chef/resource/subversion.rb +4 -0
- data/lib/chef/resource/windows_package.rb +79 -0
- data/lib/chef/resource/windows_script.rb +0 -5
- data/lib/chef/resources.rb +1 -0
- data/lib/chef/rest.rb +6 -1
- data/lib/chef/run_context.rb +22 -2
- data/lib/chef/run_context/cookbook_compiler.rb +12 -0
- data/lib/chef/util/editor.rb +92 -0
- data/lib/chef/util/file_edit.rb +22 -54
- data/lib/chef/version.rb +2 -2
- data/lib/chef/win32/api/installer.rb +166 -0
- data/lib/chef/win32/version.rb +8 -0
- data/spec/data/standalone_cookbook/Gemfile +1 -0
- data/spec/data/standalone_cookbook/chefignore +9 -0
- data/spec/data/standalone_cookbook/recipes/default.rb +3 -0
- data/spec/data/standalone_cookbook/vendor/bundle/ruby/2.0.0/gems/multi_json-1.9.0/lib/multi_json.rb +1 -0
- data/spec/functional/resource/powershell_spec.rb +262 -1
- data/spec/functional/win32/versions_spec.rb +3 -3
- data/spec/integration/knife/chefignore_spec.rb +1 -2
- data/spec/integration/knife/raw_spec.rb +8 -13
- data/spec/integration/knife/redirection_spec.rb +6 -14
- data/spec/integration/solo/solo_spec.rb +19 -0
- data/spec/support/shared/functional/windows_script.rb +1 -1
- data/spec/support/shared/integration/app_server_support.rb +42 -0
- data/spec/support/shared/integration/integration_helper.rb +1 -0
- data/spec/support/shared/unit/script_resource.rb +38 -0
- data/spec/unit/api_client/registration_spec.rb +109 -38
- data/spec/unit/application/client_spec.rb +48 -1
- data/spec/unit/cookbook/chefignore_spec.rb +10 -0
- data/spec/unit/cookbook/metadata_spec.rb +45 -1
- data/spec/unit/cookbook/syntax_check_spec.rb +28 -0
- data/spec/unit/cookbook_spec.rb +0 -10
- data/spec/unit/guard_interpreter/resource_guard_interpreter_spec.rb +56 -0
- data/spec/unit/http/simple_spec.rb +32 -0
- data/spec/unit/http/validate_content_length_spec.rb +187 -0
- data/spec/unit/knife/bootstrap_spec.rb +13 -4
- data/spec/unit/knife/client_bulk_delete_spec.rb +123 -38
- data/spec/unit/knife/client_delete_spec.rb +4 -4
- data/spec/unit/knife/cookbook_upload_spec.rb +181 -88
- data/spec/unit/knife/core/bootstrap_context_spec.rb +11 -1
- data/spec/unit/knife/core/ui_spec.rb +109 -38
- data/spec/unit/knife/node_run_list_add_spec.rb +24 -1
- data/spec/unit/knife/ssh_spec.rb +17 -6
- data/spec/unit/knife/ssl_check_spec.rb +187 -0
- data/spec/unit/knife/ssl_fetch_spec.rb +151 -0
- data/spec/unit/mixin/deep_merge_spec.rb +17 -0
- data/spec/unit/node/immutable_collections_spec.rb +55 -0
- data/spec/unit/node_spec.rb +9 -0
- data/spec/unit/platform/query_helpers_spec.rb +32 -0
- data/spec/unit/platform_spec.rb +193 -175
- data/spec/unit/policy_builder/expand_node_object_spec.rb +1 -1
- data/spec/unit/provider/cron_spec.rb +175 -1
- data/spec/unit/provider/mount/mount_spec.rb +33 -3
- data/spec/unit/provider/package/dpkg_spec.rb +4 -0
- data/spec/unit/provider/package/windows/msi_spec.rb +60 -0
- data/spec/unit/provider/package/windows_spec.rb +80 -0
- data/spec/unit/provider/service/macosx_spec.rb +3 -3
- data/spec/unit/provider/service/solaris_smf_service_spec.rb +35 -10
- data/spec/unit/pure_application_spec.rb +32 -0
- data/spec/unit/recipe_spec.rb +4 -0
- data/spec/unit/resource/conditional_spec.rb +13 -12
- data/spec/unit/resource/cron_spec.rb +7 -2
- data/spec/unit/resource/powershell_spec.rb +85 -2
- data/spec/unit/resource/subversion_spec.rb +5 -0
- data/spec/unit/resource/windows_package_spec.rb +74 -0
- data/spec/unit/resource_spec.rb +23 -1
- data/spec/unit/rest_spec.rb +15 -0
- data/spec/unit/run_context/cookbook_compiler_spec.rb +12 -0
- data/spec/unit/run_context_spec.rb +7 -0
- data/spec/unit/util/editor_spec.rb +152 -0
- data/spec/unit/util/file_edit_spec.rb +37 -1
- metadata +41 -30
@@ -62,7 +62,6 @@ class Chef
|
|
62
62
|
|
63
63
|
def config_content
|
64
64
|
client_rb = <<-CONFIG
|
65
|
-
log_level :auto
|
66
65
|
log_location STDOUT
|
67
66
|
chef_server_url "#{@chef_config[:chef_server_url]}"
|
68
67
|
validation_client_name "#{@chef_config[:validation_client_name]}"
|
@@ -93,6 +92,7 @@ CONFIG
|
|
93
92
|
# If the user doesn't have a client path configure, let bash use the PATH for what it was designed for
|
94
93
|
client_path = @chef_config[:chef_client_path] || 'chef-client'
|
95
94
|
s = "#{client_path} -j /etc/chef/first-boot.json"
|
95
|
+
s << ' -l debug' if @config[:verbosity] and @config[:verbosity] >= 2
|
96
96
|
s << " -E #{bootstrap_environment}" if chef_version.to_f != 0.9 # only use the -E option on Chef 0.10+
|
97
97
|
s
|
98
98
|
end
|
data/lib/chef/knife/core/ui.rb
CHANGED
@@ -205,24 +205,61 @@ class Chef
|
|
205
205
|
output(format_for_display(object)) if config[:print_after]
|
206
206
|
end
|
207
207
|
|
208
|
-
def
|
208
|
+
def confirmation_instructions(default_choice)
|
209
|
+
case default_choice
|
210
|
+
when true
|
211
|
+
'? (Y/n)'
|
212
|
+
when false
|
213
|
+
'? (y/N)'
|
214
|
+
else
|
215
|
+
'? (Y/N)'
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# See confirm method for argument information
|
220
|
+
def confirm_without_exit(question, append_instructions=true, default_choice=nil)
|
209
221
|
return true if config[:yes]
|
210
222
|
|
211
223
|
stdout.print question
|
212
|
-
stdout.print
|
224
|
+
stdout.print confirmation_instructions(default_choice) if append_instructions
|
225
|
+
|
213
226
|
answer = stdin.readline
|
214
227
|
answer.chomp!
|
228
|
+
|
215
229
|
case answer
|
216
230
|
when "Y", "y"
|
217
231
|
true
|
218
232
|
when "N", "n"
|
219
233
|
self.msg("You said no, so I'm done here.")
|
220
|
-
|
234
|
+
false
|
235
|
+
when ""
|
236
|
+
unless default_choice.nil?
|
237
|
+
default_choice
|
238
|
+
else
|
239
|
+
self.msg("I have no idea what to do with '#{answer}'")
|
240
|
+
self.msg("Just say Y or N, please.")
|
241
|
+
confirm_without_exit(question, append_instructions, default_choice)
|
242
|
+
end
|
221
243
|
else
|
222
|
-
self.msg("I have no idea what to do with #{answer}")
|
244
|
+
self.msg("I have no idea what to do with '#{answer}'")
|
223
245
|
self.msg("Just say Y or N, please.")
|
224
|
-
|
246
|
+
confirm_without_exit(question, append_instructions, default_choice)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
#
|
251
|
+
# Not the ideal signature for a function but we need to stick with this
|
252
|
+
# for now until we get a chance to break our API in Chef 12.
|
253
|
+
#
|
254
|
+
# question => Question to print before asking for confirmation
|
255
|
+
# append_instructions => Should print '? (Y/N)' as instructions
|
256
|
+
# default_choice => Set to true for 'Y', and false for 'N' as default answer
|
257
|
+
#
|
258
|
+
def confirm(question, append_instructions=true, default_choice=nil)
|
259
|
+
unless confirm_without_exit(question, append_instructions, default_choice)
|
260
|
+
exit 3
|
225
261
|
end
|
262
|
+
true
|
226
263
|
end
|
227
264
|
|
228
265
|
end
|
@@ -34,6 +34,11 @@ class Chef
|
|
34
34
|
:long => "--after ITEM",
|
35
35
|
:description => "Place the ENTRY in the run list after ITEM"
|
36
36
|
|
37
|
+
option :before,
|
38
|
+
:short => "-b ITEM",
|
39
|
+
:long => "--before ITEM",
|
40
|
+
:description => "Place the ENTRY in the run list before ITEM"
|
41
|
+
|
37
42
|
def run
|
38
43
|
node = Chef::Node.load(@name_args[0])
|
39
44
|
if @name_args.size > 2
|
@@ -46,7 +51,18 @@ class Chef
|
|
46
51
|
entries = @name_args[1].split(',').map { |e| e.strip }
|
47
52
|
end
|
48
53
|
|
49
|
-
|
54
|
+
if config[:after] && config[:before]
|
55
|
+
ui.fatal("You cannot specify both --before and --after!")
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
|
59
|
+
if config[:after]
|
60
|
+
add_to_run_list_after(node, entries, config[:after])
|
61
|
+
elsif config[:before]
|
62
|
+
add_to_run_list_before(node, entries, config[:before])
|
63
|
+
else
|
64
|
+
add_to_run_list_after(node, entries)
|
65
|
+
end
|
50
66
|
|
51
67
|
node.save
|
52
68
|
|
@@ -55,7 +71,9 @@ class Chef
|
|
55
71
|
output(format_for_display(node))
|
56
72
|
end
|
57
73
|
|
58
|
-
|
74
|
+
private
|
75
|
+
|
76
|
+
def add_to_run_list_after(node, entries, after=nil)
|
59
77
|
if after
|
60
78
|
nlist = []
|
61
79
|
node.run_list.each do |entry|
|
@@ -70,6 +88,17 @@ class Chef
|
|
70
88
|
end
|
71
89
|
end
|
72
90
|
|
91
|
+
def add_to_run_list_before(node, entries, before)
|
92
|
+
nlist = []
|
93
|
+
node.run_list.each do |entry|
|
94
|
+
if entry == before
|
95
|
+
entries.each { |e| nlist << e }
|
96
|
+
end
|
97
|
+
nlist << entry
|
98
|
+
end
|
99
|
+
node.run_list.reset!(nlist)
|
100
|
+
end
|
101
|
+
|
73
102
|
end
|
74
103
|
end
|
75
104
|
end
|
data/lib/chef/knife/ssh.rb
CHANGED
@@ -114,7 +114,7 @@ class Chef
|
|
114
114
|
end
|
115
115
|
case config[:on_error]
|
116
116
|
when :skip
|
117
|
-
ui.warn "Failed to connect to #{
|
117
|
+
ui.warn "Failed to connect to #{server.host} -- #{$!.class.name}: #{$!.message}"
|
118
118
|
$!.backtrace.each { |l| Chef::Log.debug(l) }
|
119
119
|
when :raise
|
120
120
|
#Net::SSH::Multi magic to force exception to be re-raised.
|
@@ -142,31 +142,9 @@ class Chef
|
|
142
142
|
end
|
143
143
|
|
144
144
|
def configure_session
|
145
|
-
list =
|
146
|
-
|
147
|
-
|
148
|
-
when false
|
149
|
-
r = Array.new
|
150
|
-
q = Chef::Search::Query.new
|
151
|
-
@action_nodes = q.search(:node, @name_args[0])[0]
|
152
|
-
@action_nodes.each do |item|
|
153
|
-
# we should skip the loop to next iteration if the item returned by the search is nil
|
154
|
-
next if item.nil?
|
155
|
-
# if a command line attribute was not passed, and we have a cloud public_hostname, use that.
|
156
|
-
# see #configure_attribute for the source of config[:attribute] and config[:override_attribute]
|
157
|
-
if !config[:override_attribute] && item[:cloud] and item[:cloud][:public_hostname]
|
158
|
-
i = item[:cloud][:public_hostname]
|
159
|
-
elsif config[:override_attribute]
|
160
|
-
i = extract_nested_value(item, config[:override_attribute])
|
161
|
-
else
|
162
|
-
i = extract_nested_value(item, config[:attribute])
|
163
|
-
end
|
164
|
-
# next if we couldn't find the specified attribute in the returned node object
|
165
|
-
next if i.nil?
|
166
|
-
r.push(i)
|
167
|
-
end
|
168
|
-
r
|
169
|
-
end
|
145
|
+
list = config[:manual] ?
|
146
|
+
@name_args[0].split(" ") :
|
147
|
+
search_nodes
|
170
148
|
if list.length == 0
|
171
149
|
if @action_nodes.length == 0
|
172
150
|
ui.fatal("No nodes returned from search!")
|
@@ -180,21 +158,54 @@ class Chef
|
|
180
158
|
session_from_list(list)
|
181
159
|
end
|
182
160
|
|
161
|
+
def search_nodes
|
162
|
+
list = Array.new
|
163
|
+
query = Chef::Search::Query.new
|
164
|
+
@action_nodes = query.search(:node, @name_args[0])[0]
|
165
|
+
@action_nodes.each do |item|
|
166
|
+
# we should skip the loop to next iteration if the item
|
167
|
+
# returned by the search is nil
|
168
|
+
next if item.nil?
|
169
|
+
# if a command line attribute was not passed, and we have a
|
170
|
+
# cloud public_hostname, use that. see #configure_attribute
|
171
|
+
# for the source of config[:attribute] and
|
172
|
+
# config[:override_attribute]
|
173
|
+
if config[:override_attribute]
|
174
|
+
host = extract_nested_value(item, config[:override_attribute])
|
175
|
+
elsif item[:cloud] && item[:cloud][:public_hostname]
|
176
|
+
host = item[:cloud][:public_hostname]
|
177
|
+
else
|
178
|
+
host = extract_nested_value(item, config[:attribute])
|
179
|
+
end
|
180
|
+
# next if we couldn't find the specified attribute in the
|
181
|
+
# returned node object
|
182
|
+
next if host.nil?
|
183
|
+
ssh_port = item[:cloud].nil? ? nil : item[:cloud][:public_ssh_port]
|
184
|
+
srv = [host, ssh_port]
|
185
|
+
list.push(srv)
|
186
|
+
end
|
187
|
+
list
|
188
|
+
end
|
189
|
+
|
183
190
|
def session_from_list(list)
|
184
191
|
list.each do |item|
|
185
|
-
|
192
|
+
host, ssh_port = item
|
193
|
+
Chef::Log.debug("Adding #{host}")
|
186
194
|
session_opts = {}
|
187
195
|
|
188
|
-
ssh_config = Net::SSH.configuration_for(
|
196
|
+
ssh_config = Net::SSH.configuration_for(host)
|
189
197
|
|
190
198
|
# Chef::Config[:knife][:ssh_user] is parsed in #configure_user and written to config[:ssh_user]
|
191
199
|
user = config[:ssh_user] || ssh_config[:user]
|
192
|
-
hostspec = user ? "#{user}@#{
|
200
|
+
hostspec = user ? "#{user}@#{host}" : host
|
193
201
|
session_opts[:keys] = File.expand_path(config[:identity_file]) if config[:identity_file]
|
194
202
|
session_opts[:keys_only] = true if config[:identity_file]
|
195
203
|
session_opts[:password] = config[:ssh_password] if config[:ssh_password]
|
196
204
|
session_opts[:forward_agent] = config[:forward_agent]
|
197
|
-
session_opts[:port] = config[:ssh_port] ||
|
205
|
+
session_opts[:port] = config[:ssh_port] ||
|
206
|
+
ssh_port || # Use cloud port if available
|
207
|
+
Chef::Config[:knife][:ssh_port] ||
|
208
|
+
ssh_config[:port]
|
198
209
|
session_opts[:logger] = Chef::Log.logger if Chef::Log.level == :debug
|
199
210
|
|
200
211
|
if !config[:host_key_verify]
|
@@ -204,7 +215,7 @@ class Chef
|
|
204
215
|
|
205
216
|
session.use(hostspec, session_opts)
|
206
217
|
|
207
|
-
@longest =
|
218
|
+
@longest = host.length if host.length > @longest
|
208
219
|
end
|
209
220
|
|
210
221
|
session
|
@@ -510,6 +521,8 @@ class Chef
|
|
510
521
|
end
|
511
522
|
end
|
512
523
|
|
524
|
+
private :search_nodes
|
525
|
+
|
513
526
|
end
|
514
527
|
end
|
515
528
|
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Daniel DeLeo (<dan@getchef.com>)
|
3
|
+
# Copyright:: Copyright (c) 2014 Chef Software, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife'
|
20
|
+
require 'chef/config'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
class SslCheck < Chef::Knife
|
25
|
+
|
26
|
+
deps do
|
27
|
+
require 'pp'
|
28
|
+
require 'socket'
|
29
|
+
require 'uri'
|
30
|
+
require 'chef/http/ssl_policies'
|
31
|
+
require 'openssl'
|
32
|
+
end
|
33
|
+
|
34
|
+
banner "knife ssl check [URL] (options)"
|
35
|
+
|
36
|
+
def initialize(*args)
|
37
|
+
@host = nil
|
38
|
+
@verify_peer_socket = nil
|
39
|
+
@ssl_policy = HTTP::DefaultSSLPolicy
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
def uri
|
44
|
+
@uri ||= begin
|
45
|
+
Chef::Log.debug("Checking SSL cert on #{given_uri}")
|
46
|
+
URI.parse(given_uri)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def given_uri
|
51
|
+
(name_args[0] or Chef::Config.chef_server_url)
|
52
|
+
end
|
53
|
+
|
54
|
+
def host
|
55
|
+
uri.host
|
56
|
+
end
|
57
|
+
|
58
|
+
def port
|
59
|
+
uri.port
|
60
|
+
end
|
61
|
+
|
62
|
+
def validate_uri
|
63
|
+
unless host && port
|
64
|
+
invalid_uri!
|
65
|
+
end
|
66
|
+
rescue URI::Error
|
67
|
+
invalid_uri!
|
68
|
+
end
|
69
|
+
|
70
|
+
def invalid_uri!
|
71
|
+
ui.error("Given URI: `#{given_uri}' is invalid")
|
72
|
+
show_usage
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def verify_peer_socket
|
78
|
+
@verify_peer_socket ||= begin
|
79
|
+
tcp_connection = TCPSocket.new(host, port)
|
80
|
+
OpenSSL::SSL::SSLSocket.new(tcp_connection, verify_peer_ssl_context)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def verify_peer_ssl_context
|
85
|
+
@verify_peer_ssl_context ||= begin
|
86
|
+
verify_peer_context = OpenSSL::SSL::SSLContext.new
|
87
|
+
@ssl_policy.apply_to(verify_peer_context)
|
88
|
+
verify_peer_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
89
|
+
verify_peer_context
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def noverify_socket
|
94
|
+
@noverify_socket ||= begin
|
95
|
+
tcp_connection = TCPSocket.new(host, port)
|
96
|
+
OpenSSL::SSL::SSLSocket.new(tcp_connection, noverify_peer_ssl_context)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def noverify_peer_ssl_context
|
101
|
+
@noverify_peer_ssl_context ||= begin
|
102
|
+
noverify_peer_context = OpenSSL::SSL::SSLContext.new
|
103
|
+
@ssl_policy.apply_to(noverify_peer_context)
|
104
|
+
noverify_peer_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
105
|
+
noverify_peer_context
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def verify_cert
|
110
|
+
ui.msg("Connecting to host #{host}:#{port}")
|
111
|
+
verify_peer_socket.connect
|
112
|
+
true
|
113
|
+
rescue OpenSSL::SSL::SSLError => e
|
114
|
+
ui.error "The SSL certificate of #{host} could not be verified"
|
115
|
+
Chef::Log.debug e.message
|
116
|
+
debug_invalid_cert
|
117
|
+
false
|
118
|
+
end
|
119
|
+
|
120
|
+
def verify_cert_host
|
121
|
+
verify_peer_socket.post_connection_check(host)
|
122
|
+
true
|
123
|
+
rescue OpenSSL::SSL::SSLError => e
|
124
|
+
ui.error "The SSL cert is signed by a trusted authority but is not valid for the given hostname"
|
125
|
+
Chef::Log.debug(e)
|
126
|
+
debug_invalid_host
|
127
|
+
false
|
128
|
+
end
|
129
|
+
|
130
|
+
def debug_invalid_cert
|
131
|
+
noverify_socket.connect
|
132
|
+
issuer_info = noverify_socket.peer_cert.issuer
|
133
|
+
ui.msg("Certificate issuer data: #{issuer_info}")
|
134
|
+
|
135
|
+
ui.msg("\n#{ui.color("Configuration Info:", :bold)}\n\n")
|
136
|
+
debug_ssl_settings
|
137
|
+
debug_chef_ssl_config
|
138
|
+
|
139
|
+
ui.err(<<-ADVICE)
|
140
|
+
|
141
|
+
#{ui.color("TO FIX THIS ERROR:", :bold)}
|
142
|
+
|
143
|
+
If the server you are connecting to uses a self-signed certificate, you must
|
144
|
+
configure chef to trust that server's certificate.
|
145
|
+
|
146
|
+
By default, the certificate is stored in the following location on the host
|
147
|
+
where your chef-server runs:
|
148
|
+
|
149
|
+
/var/opt/chef-server/nginx/ca/SERVER_HOSTNAME.crt
|
150
|
+
|
151
|
+
Copy that file to you trusted_certs_dir (currently: #{configuration.trusted_certs_dir})
|
152
|
+
using SSH/SCP or some other secure method, then re-run this command to confirm
|
153
|
+
that the server's certificate is now trusted.
|
154
|
+
|
155
|
+
ADVICE
|
156
|
+
end
|
157
|
+
|
158
|
+
def debug_invalid_host
|
159
|
+
noverify_socket.connect
|
160
|
+
subject = noverify_socket.peer_cert.subject
|
161
|
+
cn_field_tuple = subject.to_a.find {|field| field[0] == "CN" }
|
162
|
+
cn = cn_field_tuple[1]
|
163
|
+
|
164
|
+
ui.error("You are attempting to connect to: '#{host}'")
|
165
|
+
ui.error("The server's certificate belongs to '#{cn}'")
|
166
|
+
ui.err(<<-ADVICE)
|
167
|
+
|
168
|
+
#{ui.color("TO FIX THIS ERROR:", :bold)}
|
169
|
+
|
170
|
+
The solution for this issue depends on your networking configuration. If you
|
171
|
+
are able to connect to this server using the hostname #{cn}
|
172
|
+
instead of #{host}, then you can resolve this issue by updating chef_server_url
|
173
|
+
in your configuration file.
|
174
|
+
|
175
|
+
If you are not able to connect to the server using the hostname #{cn}
|
176
|
+
you will have to update the certificate on the server to use the correct hostname.
|
177
|
+
ADVICE
|
178
|
+
end
|
179
|
+
|
180
|
+
def debug_ssl_settings
|
181
|
+
ui.err "OpenSSL Configuration:"
|
182
|
+
ui.err "* Version: #{OpenSSL::OPENSSL_VERSION}"
|
183
|
+
ui.err "* Certificate file: #{OpenSSL::X509::DEFAULT_CERT_FILE}"
|
184
|
+
ui.err "* Certificate directory: #{OpenSSL::X509::DEFAULT_CERT_DIR}"
|
185
|
+
end
|
186
|
+
|
187
|
+
def debug_chef_ssl_config
|
188
|
+
ui.err "Chef SSL Configuration:"
|
189
|
+
ui.err "* ssl_ca_path: #{configuration.ssl_ca_path.inspect}"
|
190
|
+
ui.err "* ssl_ca_file: #{configuration.ssl_ca_file.inspect}"
|
191
|
+
ui.err "* trusted_certs_dir: #{configuration.trusted_certs_dir.inspect}"
|
192
|
+
end
|
193
|
+
|
194
|
+
def configuration
|
195
|
+
Chef::Config
|
196
|
+
end
|
197
|
+
|
198
|
+
def run
|
199
|
+
validate_uri
|
200
|
+
if verify_cert && verify_cert_host
|
201
|
+
ui.msg "Successfully verified certificates from `#{host}'"
|
202
|
+
else
|
203
|
+
exit 1
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
|